chiark / gitweb /
systemctl: add to command for virtualizing the dependency tree with graphviz
[elogind.git] / src / util.c
index fa3969b7051e04a248e4034e4af6f995aa081aa3..519d22902ae2f4e9edba6bf50e245a944db407b1 100644 (file)
@@ -47,6 +47,7 @@
 #include <sys/utsname.h>
 #include <pwd.h>
 #include <netinet/ip.h>
+#include <linux/kd.h>
 
 #include "macro.h"
 #include "util.h"
@@ -609,8 +610,22 @@ int get_process_cmdline(pid_t pid, size_t max_length, char **line) {
 
         fclose(f);
 
-        if (r[0] == 0)
-                return get_process_name(pid, line);
+        /* Kernel threads have no argv[] */
+        if (r[0] == 0) {
+                char *t;
+                int h;
+
+                free(r);
+
+                if ((h = get_process_name(pid, &t)) < 0)
+                        return h;
+
+                h = asprintf(&r, "[%s]", t);
+                free(t);
+
+                if (h < 0)
+                        return -ENOMEM;
+        }
 
         *line = r;
         return 0;
@@ -698,6 +713,48 @@ int readlink_and_make_absolute(const char *p, char **r) {
         return 0;
 }
 
+int parent_of_path(const char *path, char **_r) {
+        const char *e, *a = NULL, *b = NULL, *p;
+        char *r;
+        bool slash = false;
+
+        assert(path);
+        assert(_r);
+
+        if (!*path)
+                return -EINVAL;
+
+        for (e = path; *e; e++) {
+
+                if (!slash && *e == '/') {
+                        a = b;
+                        b = e;
+                        slash = true;
+                } else if (slash && *e != '/')
+                        slash = false;
+        }
+
+        if (*(e-1) == '/')
+                p = a;
+        else
+                p = b;
+
+        if (!p)
+                return -EINVAL;
+
+        if (p == path)
+                r = strdup("/");
+        else
+                r = strndup(path, p-path);
+
+        if (!r)
+                return -ENOMEM;
+
+        *_r = r;
+        return 0;
+}
+
+
 char *file_name_from_path(const char *p) {
         char *r;
 
@@ -956,7 +1013,6 @@ int mkdir_parents(const char *path, mode_t mode) {
                         return -ENOMEM;
 
                 r = mkdir(t, mode);
-
                 free(t);
 
                 if (r < 0 && errno != EEXIST)
@@ -972,7 +1028,7 @@ int mkdir_p(const char *path, mode_t mode) {
         if ((r = mkdir_parents(path, mode)) < 0)
                 return r;
 
-        if (mkdir(path, mode) < 0)
+        if (mkdir(path, mode) < 0 && errno != EEXIST)
                 return -errno;
 
         return 0;
@@ -1789,10 +1845,22 @@ int ask(char *ret, const char *replies, const char *text, ...) {
 int reset_terminal(int fd) {
         struct termios termios;
         int r = 0;
+        long arg;
+
+        /* Set terminal to some sane defaults */
 
         assert(fd >= 0);
 
-        /* Set terminal to some sane defaults */
+        /* First, unlock termios */
+        zero(termios);
+        ioctl(fd, TIOCSLCKTRMIOS, &termios);
+
+        /* Disable exclusive mode, just in case */
+        ioctl(fd, TIOCNXCL);
+
+        /* Enable console unicode mode */
+        arg = K_UNICODE;
+        ioctl(fd, KDSKBMODE, &arg);
 
         if (tcgetattr(fd, &termios) < 0) {
                 r = -errno;
@@ -1975,7 +2043,7 @@ int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocst
                         }
 
                         if (e.wd != wd || !(e.mask & IN_CLOSE)) {
-                                r = -errno;
+                                r = -EIO;
                                 goto fail;
                         }
 
@@ -2202,25 +2270,24 @@ ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
 
 int path_is_mount_point(const char *t) {
         struct stat a, b;
-        char *copy;
+        char *parent;
+        int r;
 
         if (lstat(t, &a) < 0) {
-
                 if (errno == ENOENT)
                         return 0;
 
                 return -errno;
         }
 
-        if (!(copy = strdup(t)))
-                return -ENOMEM;
+        if ((r = parent_of_path(t, &parent)) < 0)
+                return r;
 
-        if (lstat(dirname(copy), &b) < 0) {
-                free(copy);
-                return -errno;
-        }
+        r = lstat(parent, &b);
+        free(parent);
 
-        free(copy);
+        if (r < 0)
+                return -errno;
 
         return a.st_dev != b.st_dev;
 }
@@ -2498,7 +2565,8 @@ static int rm_rf_children(int fd, bool only_dirs) {
 
         if (!(d = fdopendir(fd))) {
                 close_nointr_nofail(fd);
-                return -errno;
+
+                return errno == ENOENT ? 0 : -errno;
         }
 
         for (;;) {
@@ -2522,7 +2590,7 @@ static int rm_rf_children(int fd, bool only_dirs) {
                         struct stat st;
 
                         if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
-                                if (ret == 0)
+                                if (ret == 0 && errno != ENOENT)
                                         ret = -errno;
                                 continue;
                         }
@@ -2535,7 +2603,7 @@ static int rm_rf_children(int fd, bool only_dirs) {
                         int subdir_fd;
 
                         if ((subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) {
-                                if (ret == 0)
+                                if (ret == 0 && errno != ENOENT)
                                         ret = -errno;
                                 continue;
                         }
@@ -2546,13 +2614,13 @@ static int rm_rf_children(int fd, bool only_dirs) {
                         }
 
                         if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
-                                if (ret == 0)
+                                if (ret == 0 && errno != ENOENT)
                                         ret = -errno;
                         }
                 } else  if (!only_dirs) {
 
                         if (unlinkat(fd, de->d_name, 0) < 0) {
-                                if (ret == 0)
+                                if (ret == 0 && errno != ENOENT)
                                         ret = -errno;
                         }
                 }