chiark / gitweb /
util: introduce mkdir_p()
[elogind.git] / util.c
diff --git a/util.c b/util.c
index 7306ddde34c4ee26db5cac1389f5647cfb05d409..29f48b08e3b918991350caa2794682a239b7ca5e 100644 (file)
--- a/util.c
+++ b/util.c
@@ -32,6 +32,8 @@
 #include <linux/sched.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
 
 #include "macro.h"
 #include "util.h"
 #include "log.h"
 #include "strv.h"
 
+bool streq_ptr(const char *a, const char *b) {
+
+        /* Like streq(), but tries to make sense of NULL pointers */
+
+        if (a && b)
+                return streq(a, b);
+
+        if (!a && !b)
+                return true;
+
+        return false;
+}
+
 usec_t now(clockid_t clock_id) {
         struct timespec ts;
 
@@ -410,7 +425,7 @@ finish:
 int read_one_line_file(const char *fn, char **line) {
         FILE *f;
         int r;
-        char t[64], *c;
+        char t[2048], *c;
 
         assert(fn);
         assert(line);
@@ -436,6 +451,33 @@ finish:
         return r;
 }
 
+char *truncate_nl(char *s) {
+        assert(s);
+
+        s[strcspn(s, NEWLINE)] = 0;
+        return s;
+}
+
+int get_process_name(pid_t pid, char **name) {
+        char *p;
+        int r;
+
+        assert(pid >= 1);
+        assert(name);
+
+        if (asprintf(&p, "/proc/%llu/comm", (unsigned long long) pid) < 0)
+                return -ENOMEM;
+
+        r = read_one_line_file(p, name);
+        free(p);
+
+        if (r < 0)
+                return r;
+
+        truncate_nl(*name);
+        return 0;
+}
+
 char *strappend(const char *s, const char *suffix) {
         size_t a, b;
         char *r;
@@ -609,6 +651,23 @@ char *strstrip(char *s) {
 
 }
 
+char *delete_chars(char *s, const char *bad) {
+        char *f, *t;
+
+        /* Drops all whitespace, regardless where in the string */
+
+        for (f = s, t = s; *f; f++) {
+                if (strchr(bad, *f))
+                        continue;
+
+                *(t++) = *f;
+        }
+
+        *t = 0;
+
+        return s;
+}
+
 char *file_in_same_dir(const char *path, const char *filename) {
         char *e, *r;
         size_t k;
@@ -669,6 +728,20 @@ int mkdir_parents(const char *path, mode_t mode) {
         }
 }
 
+int mkdir_p(const char *path, mode_t mode) {
+        int r;
+
+        /* Like mkdir -p */
+
+        if ((r = mkdir_parents(path, mode)) < 0)
+                return r;
+
+        if (mkdir(path, mode) < 0)
+                return -errno;
+
+        return 0;
+}
+
 char hexchar(int x) {
         static const char table[16] = "0123456789abcdef";
 
@@ -1058,16 +1131,16 @@ bool path_startswith(const char *path, const char *prefix) {
         }
 }
 
-char *ascii_strlower(char *path) {
+char *ascii_strlower(char *t) {
         char *p;
 
-        assert(path);
+        assert(t);
 
-        for (p = path; *p; p++)
+        for (p = t; *p; p++)
                 if (*p >= 'A' && *p <= 'Z')
                         *p = *p - 'A' + 'a';
 
-        return p;
+        return t;
 }
 
 bool ignore_file(const char *filename) {
@@ -1084,6 +1157,107 @@ bool ignore_file(const char *filename) {
                 endswith(filename, ".swp");
 }
 
+int fd_nonblock(int fd, bool nonblock) {
+        int flags;
+
+        assert(fd >= 0);
+
+        if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
+                return -errno;
+
+        if (nonblock)
+                flags |= O_NONBLOCK;
+        else
+                flags &= ~O_NONBLOCK;
+
+        if (fcntl(fd, F_SETFL, flags) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int fd_cloexec(int fd, bool cloexec) {
+        int flags;
+
+        assert(fd >= 0);
+
+        if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
+                return -errno;
+
+        if (cloexec)
+                flags |= FD_CLOEXEC;
+        else
+                flags &= ~FD_CLOEXEC;
+
+        if (fcntl(fd, F_SETFD, flags) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int close_all_fds(const int except[], unsigned n_except) {
+        DIR *d;
+        struct dirent *de;
+        int r = 0;
+
+        if (!(d = opendir("/proc/self/fd")))
+                return -errno;
+
+        while ((de = readdir(d))) {
+                int fd = -1;
+
+                if (de->d_name[0] == '.')
+                        continue;
+
+                if ((r = safe_atoi(de->d_name, &fd)) < 0)
+                        goto finish;
+
+                if (fd < 3)
+                        continue;
+
+                if (fd == dirfd(d))
+                        continue;
+
+                if (except) {
+                        bool found;
+                        unsigned i;
+
+                        found = false;
+                        for (i = 0; i < n_except; i++)
+                                if (except[i] == fd) {
+                                        found = true;
+                                        break;
+                                }
+
+                        if (found)
+                                continue;
+                }
+
+                if ((r = close_nointr(fd)) < 0) {
+                        /* Valgrind has its own FD and doesn't want to have it closed */
+                        if (errno != EBADF)
+                                goto finish;
+                }
+        }
+
+        r = 0;
+
+finish:
+        closedir(d);
+        return r;
+}
+
+bool chars_intersect(const char *a, const char *b) {
+        const char *p;
+
+        /* Returns true if any of the chars in a are in b. */
+        for (p = a; *p; p++)
+                if (strchr(b, *p))
+                        return true;
+
+        return false;
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",