chiark / gitweb /
core: priorize notification fd processing over notification fd process via sd-event...
[elogind.git] / src / shared / util.c
index 0fce2537da1c77ae225668c50bcba4290597af62..f59897105a6354e1cea1c7261517e2a556c660ce 100644 (file)
@@ -59,6 +59,7 @@
 #include <langinfo.h>
 #include <locale.h>
 #include <libgen.h>
+#undef basename
 
 #include "macro.h"
 #include "util.h"
@@ -85,7 +86,7 @@ static volatile unsigned cached_columns = 0;
 static volatile unsigned cached_lines = 0;
 
 size_t page_size(void) {
-        static __thread size_t pgsz = 0;
+        static thread_local size_t pgsz = 0;
         long r;
 
         if (_likely_(pgsz > 0))
@@ -430,7 +431,7 @@ char *split_quoted(const char *c, size_t *l, char **state) {
                 *state = (char*) e;
         }
 
-        return current;
+        return (char*) current;
 }
 
 int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
@@ -497,7 +498,7 @@ int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
 
         f = fopen(p, "re");
         if (!f)
-                return -errno;
+                return errno == ENOENT ? -ESRCH : -errno;
 
         if (!fgets(line, sizeof(line), f)) {
                 if (ferror(f))
@@ -563,6 +564,7 @@ char *truncate_nl(char *s) {
 
 int get_process_comm(pid_t pid, char **name) {
         const char *p;
+        int r;
 
         assert(name);
         assert(pid >= 0);
@@ -572,7 +574,11 @@ int get_process_comm(pid_t pid, char **name) {
         else
                 p = procfs_file_alloca(pid, "comm");
 
-        return read_one_line_file(p, name);
+        r = read_one_line_file(p, name);
+        if (r == -ENOENT)
+                return -ESRCH;
+
+        return r;
 }
 
 int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
@@ -729,7 +735,7 @@ int get_process_exe(pid_t pid, char **name) {
 
         r = readlink_malloc(p, name);
         if (r < 0)
-                return r;
+                return r == -ENOENT ? -ESRCH : r;
 
         d = endswith(*name, " (deleted)");
         if (d)
@@ -2496,7 +2502,7 @@ int getttyname_malloc(int fd, char **r) {
         assert(r);
 
         k = ttyname_r(fd, path, sizeof(path));
-        if (k != 0)
+        if (k > 0)
                 return -k;
 
         char_array_0(path);
@@ -2731,9 +2737,9 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct
 
 _pure_ static int is_temporary_fs(struct statfs *s) {
         assert(s);
-        return
-                F_TYPE_EQUAL(s->f_type, TMPFS_MAGIC) ||
-                F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
+
+        return F_TYPE_EQUAL(s->f_type, TMPFS_MAGIC) ||
+               F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
 }
 
 int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
@@ -3463,7 +3469,7 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid) {
         return -EPROTO;
 }
 
-_noreturn_ void freeze(void) {
+noreturn void freeze(void) {
 
         /* Make sure nobody waits for us on a socket anymore */
         close_all_fds(NULL, 0);
@@ -3956,8 +3962,8 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
         if (!t)
                 return -ENOMEM;
 
-        fn = path_get_file_name(path);
-        k = fn-path;
+        fn = basename(path);
+        k = fn - path;
         memcpy(t, path, k);
         t[k] = '.';
         stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
@@ -4142,7 +4148,7 @@ int symlink_atomic(const char *from, const char *to) {
         if (!t)
                 return -ENOMEM;
 
-        fn = path_get_file_name(to);
+        fn = basename(to);
         k = fn-to;
         memcpy(t, to, k);
         t[k] = '.';
@@ -4574,7 +4580,7 @@ char *strjoin(const char *x, ...) {
 }
 
 bool is_main_thread(void) {
-        static __thread int cached = 0;
+        static thread_local int cached = 0;
 
         if (_unlikely_(cached == 0))
                 cached = getpid() == gettid() ? 1 : -1;
@@ -4792,7 +4798,7 @@ static const char *const __signal_table[] = {
 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
 
 const char *signal_to_string(int signo) {
-        static __thread char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
+        static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
         const char *name;
 
         name = __signal_to_string(signo);
@@ -4930,15 +4936,15 @@ int fd_inc_sndbuf(int fd, size_t n) {
         socklen_t l = sizeof(value);
 
         r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
-        if (r >= 0 &&
-            l == sizeof(value) &&
-            (size_t) value >= n*2)
+        if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
                 return 0;
 
+        /* If we have the privileges we will ignore the kernel limit. */
+
         value = (int) n;
-        r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
-        if (r < 0)
-                return -errno;
+        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
+                if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
+                        return -errno;
 
         return 1;
 }
@@ -4948,16 +4954,15 @@ int fd_inc_rcvbuf(int fd, size_t n) {
         socklen_t l = sizeof(value);
 
         r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
-        if (r >= 0 &&
-            l == sizeof(value) &&
-            (size_t) value >= n*2)
+        if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
                 return 0;
 
-        value = (int) n;
-        r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
-        if (r < 0)
-                return -errno;
+        /* If we have the privileges we will ignore the kernel limit. */
 
+        value = (int) n;
+        if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
+                if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
+                        return -errno;
         return 1;
 }
 
@@ -5149,7 +5154,7 @@ bool is_valid_documentation_url(const char *url) {
 }
 
 bool in_initrd(void) {
-        static __thread int saved = -1;
+        static int saved = -1;
         struct statfs s;
 
         if (saved >= 0)
@@ -5214,10 +5219,10 @@ int make_console_stdio(void) {
 }
 
 int get_home_dir(char **_h) {
-        char *h;
+        struct passwd *p;
         const char *e;
+        char *h;
         uid_t u;
-        struct passwd *p;
 
         assert(_h);
 
@@ -5260,6 +5265,53 @@ int get_home_dir(char **_h) {
         return 0;
 }
 
+int get_shell(char **_s) {
+        struct passwd *p;
+        const char *e;
+        char *s;
+        uid_t u;
+
+        assert(_s);
+
+        /* Take the user specified one */
+        e = getenv("SHELL");
+        if (e) {
+                s = strdup(e);
+                if (!s)
+                        return -ENOMEM;
+
+                *_s = s;
+                return 0;
+        }
+
+        /* Hardcode home directory for root to avoid NSS */
+        u = getuid();
+        if (u == 0) {
+                s = strdup("/bin/sh");
+                if (!s)
+                        return -ENOMEM;
+
+                *_s = s;
+                return 0;
+        }
+
+        /* Check the database... */
+        errno = 0;
+        p = getpwuid(u);
+        if (!p)
+                return errno > 0 ? -errno : -ESRCH;
+
+        if (!path_is_absolute(p->pw_shell))
+                return -EINVAL;
+
+        s = strdup(p->pw_shell);
+        if (!s)
+                return -ENOMEM;
+
+        *_s = s;
+        return 0;
+}
+
 bool filename_is_safe(const char *p) {
 
         if (isempty(p))
@@ -5374,7 +5426,7 @@ bool is_locale_utf8(void) {
                 goto out;
         }
 
-        if(streq(set, "UTF-8")) {
+        if (streq(set, "UTF-8")) {
                 cached_answer = true;
                 goto out;
         }
@@ -5786,10 +5838,18 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) {
         size_t a;
         void *q;
 
+        assert(p);
+        assert(allocated);
+
         if (*allocated >= need)
                 return *p;
 
         a = MAX(64u, need * 2);
+
+        /* check for overflows */
+        if (a < need)
+                return NULL;
+
         q = realloc(*p, a);
         if (!q)
                 return NULL;
@@ -5799,6 +5859,25 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) {
         return q;
 }
 
+void* greedy_realloc0(void **p, size_t *allocated, size_t need) {
+        size_t prev;
+        uint8_t *q;
+
+        assert(p);
+        assert(allocated);
+
+        prev = *allocated;
+
+        q = greedy_realloc(p, allocated, need);
+        if (!q)
+                return NULL;
+
+        if (*allocated > prev)
+                memset(&q[prev], 0, *allocated - prev);
+
+        return q;
+}
+
 bool id128_is_valid(const char *s) {
         size_t i, l;
 
@@ -5898,7 +5977,7 @@ int shall_restore_state(void) {
                 return 1;
 
         FOREACH_WORD_QUOTED(w, l, line, state)
-                if (l == 23 && memcmp(w, "systemd.restore_state=0", 23))
+                if (l == 23 && strneq(w, "systemd.restore_state=0", 23))
                         return 0;
 
         return 1;
@@ -5918,3 +5997,104 @@ int proc_cmdline(char **ret) {
 
         return 1;
 }
+
+int container_get_leader(const char *machine, pid_t *pid) {
+        _cleanup_free_ char *s = NULL, *class = NULL;
+        const char *p;
+        pid_t leader;
+        int r;
+
+        assert(machine);
+        assert(pid);
+
+        p = strappenda("/run/systemd/machines/", machine);
+        r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
+        if (r == -ENOENT)
+                return -EHOSTDOWN;
+        if (r < 0)
+                return r;
+        if (!s)
+                return -EIO;
+
+        if (!streq_ptr(class, "container"))
+                return -EIO;
+
+        r = parse_pid(s, &leader);
+        if (r < 0)
+                return r;
+        if (leader <= 1)
+                return -EIO;
+
+        *pid = leader;
+        return 0;
+}
+
+int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *root_fd) {
+        _cleanup_close_ int pidnsfd = -1, mntnsfd = -1;
+        const char *pidns, *mntns, *root;
+        int rfd;
+
+        assert(pid >= 0);
+        assert(pidns_fd);
+        assert(mntns_fd);
+        assert(root_fd);
+
+        mntns = procfs_file_alloca(pid, "ns/mnt");
+        mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
+        if (mntnsfd < 0)
+                return -errno;
+
+        pidns = procfs_file_alloca(pid, "ns/pid");
+        pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
+        if (pidnsfd < 0)
+                return -errno;
+
+        root = procfs_file_alloca(pid, "root");
+        rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+        if (rfd < 0)
+                return -errno;
+
+        *pidns_fd = pidnsfd;
+        *mntns_fd = mntnsfd;
+        *root_fd = rfd;
+        pidnsfd = -1;
+        mntnsfd = -1;
+
+        return 0;
+}
+
+int namespace_enter(int pidns_fd, int mntns_fd, int root_fd) {
+        assert(pidns_fd >= 0);
+        assert(mntns_fd >= 0);
+        assert(root_fd >= 0);
+
+        if (setns(pidns_fd, CLONE_NEWPID) < 0)
+                return -errno;
+
+        if (setns(mntns_fd, CLONE_NEWNS) < 0)
+                return -errno;
+
+        if (fchdir(root_fd) < 0)
+                return -errno;
+
+        if (chroot(".") < 0)
+                return -errno;
+
+        if (setresgid(0, 0, 0) < 0)
+                return -errno;
+
+        if (setresuid(0, 0, 0) < 0)
+                return -errno;
+
+        return 0;
+}
+
+bool pid_valid(pid_t pid) {
+        if (pid <= 0)
+                return false;
+
+        if (kill(pid, 0) >= 0)
+                return true;
+
+        return errno != ESRCH;
+}