chiark / gitweb /
util: fix overflow checks
[elogind.git] / src / shared / util.c
index d94bc695c8294dce8fef4ab4bb69c190255c6959..be94515d9d8740e852a8fa56ca461676d2456bd6 100644 (file)
@@ -78,10 +78,10 @@ size_t page_size(void) {
         if (_likely_(pgsz > 0))
                 return pgsz;
 
-        assert_se((r = sysconf(_SC_PAGESIZE)) > 0);
+        r = sysconf(_SC_PAGESIZE);
+        assert(r > 0);
 
         pgsz = (size_t) r;
-
         return pgsz;
 }
 
@@ -223,10 +223,9 @@ bool startswith_no_case(const char *s, const char *prefix) {
         if (sl < pl)
                 return false;
 
-        for(i = 0; i < pl; ++i) {
+        for(i = 0; i < pl; ++i)
                 if (tolower(s[i]) != tolower(prefix[i]))
                         return false;
-        }
 
         return true;
 }
@@ -305,7 +304,8 @@ int parse_pid(const char *s, pid_t* ret_pid) {
         assert(s);
         assert(ret_pid);
 
-        if ((r = safe_atolu(s, &ul)) < 0)
+        r = safe_atolu(s, &ul);
+        if (r < 0)
                 return r;
 
         pid = (pid_t) ul;
@@ -328,7 +328,8 @@ int parse_uid(const char *s, uid_t* ret_uid) {
         assert(s);
         assert(ret_uid);
 
-        if ((r = safe_atolu(s, &ul)) < 0)
+        r = safe_atolu(s, &ul);
+        if (r < 0)
                 return r;
 
         uid = (uid_t) ul;
@@ -489,7 +490,7 @@ char *split_quoted(const char *c, size_t *l, char **state) {
 
 int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
         int r;
-        FILE *f;
+        _cleanup_fclose_ FILE *f = NULL;
         char fn[PATH_MAX], line[LINE_MAX], *p;
         long unsigned ppid;
 
@@ -499,22 +500,22 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
         assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
         char_array_0(fn);
 
-        if (!(f = fopen(fn, "re")))
+        f = fopen(fn, "re");
+        if (!f)
                 return -errno;
 
-        if (!(fgets(line, sizeof(line), f))) {
+        if (!fgets(line, sizeof(line), f)) {
                 r = feof(f) ? -EIO : -errno;
                 fclose(f);
                 return r;
         }
 
-        fclose(f);
-
         /* Let's skip the pid and comm fields. The latter is enclosed
          * in () but does not escape any () in its value, so let's
          * skip over it manually */
 
-        if (!(p = strrchr(line, ')')))
+        p = strrchr(line, ')');
+        if (!p)
                 return -EIO;
 
         p++;
@@ -534,8 +535,7 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
 }
 
 int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
-        int r;
-        FILE *f;
+        _cleanup_fclose_ FILE *f = NULL;
         char fn[PATH_MAX], line[LINE_MAX], *p;
 
         assert(pid > 0);
@@ -544,22 +544,23 @@ int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
         assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
         char_array_0(fn);
 
-        if (!(f = fopen(fn, "re")))
+        f = fopen(fn, "re");
+        if (!f)
                 return -errno;
 
-        if (!(fgets(line, sizeof(line), f))) {
-                r = feof(f) ? -EIO : -errno;
-                fclose(f);
-                return r;
-        }
+        if (!fgets(line, sizeof(line), f)) {
+                if (ferror(f))
+                        return -errno;
 
-        fclose(f);
+                return -EIO;
+        }
 
         /* Let's skip the pid and comm fields. The latter is enclosed
          * in () but does not escape any () in its value, so let's
          * skip over it manually */
 
-        if (!(p = strrchr(line, ')')))
+        p = strrchr(line, ')');
+        if (!p)
                 return -EIO;
 
         p++;
@@ -592,8 +593,7 @@ int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
 }
 
 int write_one_line_file(const char *fn, const char *line) {
-        FILE *f;
-        int r;
+        _cleanup_fclose_ FILE *f = NULL;
 
         assert(fn);
         assert(line);
@@ -603,27 +603,18 @@ int write_one_line_file(const char *fn, const char *line) {
                 return -errno;
 
         errno = 0;
-        if (fputs(line, f) < 0) {
-                r = -errno;
-                goto finish;
-        }
+        if (fputs(line, f) < 0)
+                return errno ? -errno : -EIO;
 
         if (!endswith(line, "\n"))
                 fputc('\n', f);
 
         fflush(f);
 
-        if (ferror(f)) {
-                if (errno != 0)
-                        r = -errno;
-                else
-                        r = -EIO;
-        } else
-                r = 0;
+        if (ferror(f))
+                return errno ? -errno : -EIO;
 
-finish:
-        fclose(f);
-        return r;
+        return 0;
 }
 
 int fchmod_umask(int fd, mode_t m) {
@@ -685,8 +676,7 @@ finish:
 }
 
 int read_one_line_file(const char *fn, char **line) {
-        FILE *f;
-        int r;
+        _cleanup_fclose_ FILE *f = NULL;
         char t[LINE_MAX], *c;
 
         assert(fn);
@@ -698,50 +688,37 @@ int read_one_line_file(const char *fn, char **line) {
 
         if (!fgets(t, sizeof(t), f)) {
 
-                if (ferror(f)) {
-                        r = -errno;
-                        goto finish;
-                }
+                if (ferror(f))
+                        return errno ? -errno : -EIO;
 
                 t[0] = 0;
         }
 
         c = strdup(t);
-        if (!c) {
-                r = -ENOMEM;
-                goto finish;
-        }
-
+        if (!c)
+                return -ENOMEM;
         truncate_nl(c);
 
         *line = c;
-        r = 0;
-
-finish:
-        fclose(f);
-        return r;
+        return 0;
 }
 
 int read_full_file(const char *fn, char **contents, size_t *size) {
-        FILE *f;
-        int r;
+        _cleanup_fclose_ FILE *f = NULL;
         size_t n, l;
-        char *buf = NULL;
+        _cleanup_free_ char *buf = NULL;
         struct stat st;
 
-        if (!(f = fopen(fn, "re")))
+        f = fopen(fn, "re");
+        if (!f)
                 return -errno;
 
-        if (fstat(fileno(f), &st) < 0) {
-                r = -errno;
-                goto finish;
-        }
+        if (fstat(fileno(f), &st) < 0)
+                return -errno;
 
         /* Safety check */
-        if (st.st_size > 4*1024*1024) {
-                r = -E2BIG;
-                goto finish;
-        }
+        if (st.st_size > 4*1024*1024)
+                return -E2BIG;
 
         n = st.st_size > 0 ? st.st_size : LINE_MAX;
         l = 0;
@@ -750,19 +727,16 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
                 char *t;
                 size_t k;
 
-                if (!(t = realloc(buf, n+1))) {
-                        r = -ENOMEM;
-                        goto finish;
-                }
+                t = realloc(buf, n+1);
+                if (!t)
+                        return -ENOMEM;
 
                 buf = t;
                 k = fread(buf + l, 1, n - l, f);
 
                 if (k <= 0) {
-                        if (ferror(f)) {
-                                r = -errno;
-                                goto finish;
-                        }
+                        if (ferror(f))
+                                return -errno;
 
                         break;
                 }
@@ -771,10 +745,8 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
                 n *= 2;
 
                 /* Safety check */
-                if (n > 4*1024*1024) {
-                        r = -E2BIG;
-                        goto finish;
-                }
+                if (n > 4*1024*1024)
+                        return -E2BIG;
         }
 
         buf[l] = 0;
@@ -784,13 +756,7 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
         if (size)
                 *size = l;
 
-        r = 0;
-
-finish:
-        fclose(f);
-        free(buf);
-
-        return r;
+        return 0;
 }
 
 int parse_env_file(
@@ -1142,7 +1108,7 @@ int get_process_exe(pid_t pid, char **name) {
         return r;
 }
 
-int get_process_uid(pid_t pid, uid_t *uid) {
+static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
         char *p;
         FILE *f;
         int r;
@@ -1174,8 +1140,8 @@ int get_process_uid(pid_t pid, uid_t *uid) {
 
                 l = strstrip(line);
 
-                if (startswith(l, "Uid:")) {
-                        l += 4;
+                if (startswith(l, field)) {
+                        l += strlen(field);
                         l += strspn(l, WHITESPACE);
 
                         l[strcspn(l, WHITESPACE)] = 0;
@@ -1193,6 +1159,14 @@ finish:
         return r;
 }
 
+int get_process_uid(pid_t pid, uid_t *uid) {
+        return get_process_id(pid, "Uid:", uid);
+}
+
+int get_process_gid(pid_t pid, gid_t *gid) {
+        return get_process_id(pid, "Gid:", gid);
+}
+
 char *strnappend(const char *s, const char *suffix, size_t b) {
         size_t a;
         char *r;
@@ -1210,8 +1184,11 @@ char *strnappend(const char *s, const char *suffix, size_t b) {
         assert(suffix);
 
         a = strlen(s);
+        if (b > ((size_t) -1) - a)
+                return NULL;
 
-        if (!(r = new(char, a+b+1)))
+        r = new(char, a+b+1);
+        if (!r)
                 return NULL;
 
         memcpy(r, s, a);
@@ -2077,29 +2054,23 @@ char *format_timespan(char *buf, size_t l, usec_t t) {
 }
 
 bool fstype_is_network(const char *fstype) {
-        static const char * const table[] = {
-                "cifs",
-                "smbfs",
-                "ncpfs",
-                "nfs",
-                "nfs4",
-                "gfs",
-                "gfs2"
-        };
-
-        unsigned i;
-
-        for (i = 0; i < ELEMENTSOF(table); i++)
-                if (streq(table[i], fstype))
-                        return true;
+        static const char table[] =
+                "cifs\0"
+                "smbfs\0"
+                "ncpfs\0"
+                "nfs\0"
+                "nfs4\0"
+                "gfs\0"
+                "gfs2\0";
 
-        return false;
+        return nulstr_contains(table, fstype);
 }
 
 int chvt(int vt) {
-        int fd, r = 0;
+        _cleanup_close_ int fd;
 
-        if ((fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
+        fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0)
                 return -errno;
 
         if (vt < 0) {
@@ -2108,20 +2079,16 @@ int chvt(int vt) {
                         0
                 };
 
-                if (ioctl(fd, TIOCLINUX, tiocl) < 0) {
-                        r = -errno;
-                        goto fail;
-                }
+                if (ioctl(fd, TIOCLINUX, tiocl) < 0)
+                        return -errno;
 
                 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
         }
 
         if (ioctl(fd, VT_ACTIVATE, vt) < 0)
-                r = -errno;
+                return -errno;
 
-fail:
-        close_nointr_nofail(fd);
-        return r;
+        return 0;
 }
 
 int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
@@ -2948,9 +2915,9 @@ int make_stdio(int fd) {
 
         assert(fd >= 0);
 
-        r = dup2(fd, STDIN_FILENO);
-        s = dup2(fd, STDOUT_FILENO);
-        t = dup2(fd, STDERR_FILENO);
+        r = dup3(fd, STDIN_FILENO, 0);
+        s = dup3(fd, STDOUT_FILENO, 0);
+        t = dup3(fd, STDERR_FILENO, 0);
 
         if (fd >= 3)
                 close_nointr_nofail(fd);
@@ -2958,9 +2925,7 @@ int make_stdio(int fd) {
         if (r < 0 || s < 0 || t < 0)
                 return -errno;
 
-        fd_cloexec(STDIN_FILENO, false);
-        fd_cloexec(STDOUT_FILENO, false);
-        fd_cloexec(STDERR_FILENO, false);
+        /* We rely here that the new fd has O_CLOEXEC not set */
 
         return 0;
 }
@@ -2986,36 +2951,31 @@ bool is_device_path(const char *path) {
 }
 
 int dir_is_empty(const char *path) {
-        DIR *d;
+        _cleanup_closedir_ DIR *d;
         int r;
-        struct dirent buf, *de;
 
-        if (!(d = opendir(path)))
+        d = opendir(path);
+        if (!d)
                 return -errno;
 
         for (;;) {
-                if ((r = readdir_r(d, &buf, &de)) > 0) {
-                        r = -r;
-                        break;
-                }
+                struct dirent *de;
+                union dirent_storage buf;
 
-                if (!de) {
-                        r = 1;
-                        break;
-                }
+                r = readdir_r(d, &buf.de, &de);
+                if (r > 0)
+                        return -r;
 
-                if (!ignore_file(de->d_name)) {
-                        r = 0;
-                        break;
-                }
-        }
+                if (!de)
+                        return 1;
 
-        closedir(d);
-        return r;
+                if (!ignore_file(de->d_name))
+                        return 0;
+        }
 }
 
 unsigned long long random_ull(void) {
-        int fd;
+        _cleanup_close_ int fd;
         uint64_t ull;
         ssize_t r;
 
@@ -3024,8 +2984,6 @@ unsigned long long random_ull(void) {
                 goto fallback;
 
         r = loop_read(fd, &ull, sizeof(ull), true);
-        close_nointr_nofail(fd);
-
         if (r != sizeof(ull))
                 goto fallback;
 
@@ -3099,7 +3057,8 @@ bool hostname_is_set(void) {
 
 static char *lookup_uid(uid_t uid) {
         long bufsize;
-        char *buf, *name;
+        char *name;
+        _cleanup_free_ char *buf = NULL;
         struct passwd pwbuf, *pw = NULL;
 
         /* Shortcut things to avoid NSS lookups */
@@ -3114,13 +3073,8 @@ static char *lookup_uid(uid_t uid) {
         if (!buf)
                 return NULL;
 
-        if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) {
-                name = strdup(pw->pw_name);
-                free(buf);
-                return name;
-        }
-
-        free(buf);
+        if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
+                return strdup(pw->pw_name);
 
         if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
                 return NULL;
@@ -3156,12 +3110,14 @@ int getttyname_malloc(int fd, char **r) {
 
         assert(r);
 
-        if ((k = ttyname_r(fd, path, sizeof(path))) != 0)
+        k = ttyname_r(fd, path, sizeof(path));
+        if (k != 0)
                 return -k;
 
         char_array_0(path);
 
-        if (!(c = strdup(startswith(path, "/dev/") ? path + 5 : path)))
+        c = strdup(startswith(path, "/dev/") ? path + 5 : path);
+        if (!c)
                 return -ENOMEM;
 
         *r = c;
@@ -3172,7 +3128,8 @@ int getttyname_harder(int fd, char **r) {
         int k;
         char *s;
 
-        if ((k = getttyname_malloc(fd, &s)) < 0)
+        k = getttyname_malloc(fd, &s);
+        if (k < 0)
                 return k;
 
         if (streq(s, "tty")) {
@@ -3307,12 +3264,13 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct
         }
 
         for (;;) {
-                struct dirent buf, *de;
+                struct dirent *de;
+                union dirent_storage buf;
                 bool is_dir, keep_around;
                 struct stat st;
                 int r;
 
-                r = readdir_r(d, &buf, &de);
+                r = readdir_r(d, &buf.de, &de);
                 if (r != 0 && ret == 0) {
                         ret = -r;
                         break;
@@ -3358,7 +3316,7 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct
                                 continue;
                         }
 
-                        r = rm_rf_children(subdir_fd, only_dirs, honour_sticky, root_dev);
+                        r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
                         if (r < 0 && ret == 0)
                                 ret = r;
 
@@ -3543,10 +3501,10 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
         }
 }
 
-void status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
-        char *s = NULL;
+int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
         static const char status_indent[] = "         "; /* "[" STATUS "] " */
-        int fd = -1;
+        _cleanup_free_ char *s = NULL;
+        _cleanup_close_ int fd = -1;
         struct iovec iovec[5];
         int n = 0;
 
@@ -3556,11 +3514,11 @@ void status_vprintf(const char *status, bool ellipse, const char *format, va_lis
          * optional and go exclusively to the console. */
 
         if (vasprintf(&s, format, ap) < 0)
-                goto finish;
+                return log_oom();
 
         fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
         if (fd < 0)
-                goto finish;
+                return fd;
 
         if (ellipse) {
                 char *e;
@@ -3571,7 +3529,7 @@ void status_vprintf(const char *status, bool ellipse, const char *format, va_lis
                 if (c <= 0)
                         c = 80;
 
-                sl = status ? strlen(status_indent) : 0;
+                sl = status ? sizeof(status_indent)-1 : 0;
 
                 emax = c - sl - 1;
                 if (emax < 3)
@@ -3598,53 +3556,40 @@ void status_vprintf(const char *status, bool ellipse, const char *format, va_lis
         IOVEC_SET_STRING(iovec[n++], s);
         IOVEC_SET_STRING(iovec[n++], "\n");
 
-        writev(fd, iovec, n);
-
-finish:
-        free(s);
+        if (writev(fd, iovec, n) < 0)
+                return -errno;
 
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        return 0;
 }
 
-void status_printf(const char *status, bool ellipse, const char *format, ...) {
+int status_printf(const char *status, bool ellipse, const char *format, ...) {
         va_list ap;
+        int r;
 
         assert(format);
 
         va_start(ap, format);
-        status_vprintf(status, ellipse, format, ap);
+        r = status_vprintf(status, ellipse, format, ap);
         va_end(ap);
+
+        return r;
 }
 
-void status_welcome(void) {
-        char *pretty_name = NULL, *ansi_color = NULL;
-        const char *const_pretty = NULL, *const_color = NULL;
+int status_welcome(void) {
         int r;
+        _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
 
-        if ((r = parse_env_file("/etc/os-release", NEWLINE,
-                                "PRETTY_NAME", &pretty_name,
-                                "ANSI_COLOR", &ansi_color,
-                                NULL)) < 0) {
+        r = parse_env_file("/etc/os-release", NEWLINE,
+                           "PRETTY_NAME", &pretty_name,
+                           "ANSI_COLOR", &ansi_color,
+                           NULL);
+        if (r < 0 && r != -ENOENT)
+                log_warning("Failed to read /etc/os-release: %s", strerror(-r));
 
-                if (r != -ENOENT)
-                        log_warning("Failed to read /etc/os-release: %s", strerror(-r));
-        }
-
-        if (!pretty_name && !const_pretty)
-                const_pretty = "Linux";
-
-        if (!ansi_color && !const_color)
-                const_color = "1";
-
-        status_printf(NULL,
-                      false,
-                      "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
-                      const_color ? const_color : ansi_color,
-                      const_pretty ? const_pretty : pretty_name);
-
-        free(ansi_color);
-        free(pretty_name);
+        return status_printf(NULL, false,
+                             "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
+                             isempty(ansi_color) ? "1" : ansi_color,
+                             isempty(pretty_name) ? "Linux" : pretty_name);
 }
 
 char *replace_env(const char *format, char **env) {
@@ -3923,7 +3868,12 @@ int touch(const char *path) {
 
         assert(path);
 
-        if ((fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644)) < 0)
+        /* This just opens the file for writing, ensuring it
+         * exists. It doesn't call utimensat() the way /usr/bin/touch
+         * does it. */
+
+        fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
+        if (fd < 0)
                 return -errno;
 
         close_nointr_nofail(fd);
@@ -3934,6 +3884,11 @@ char *unquote(const char *s, const char* quotes) {
         size_t l;
         assert(s);
 
+        /* This is rather stupid, simply removes the heading and
+         * trailing quotes if there is one. Doesn't care about
+         * escaping or anything. We should make this smarter one
+         * day...*/
+
         l = strlen(s);
         if (l < 2)
                 return strdup(s);
@@ -3945,39 +3900,40 @@ char *unquote(const char *s, const char* quotes) {
 }
 
 char *normalize_env_assignment(const char *s) {
-        char *name, *value, *p, *r;
+        _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
+        char *eq, *r;
 
-        p = strchr(s, '=');
+        eq = strchr(s, '=');
+        if (!eq) {
+                char *t;
 
-        if (!p) {
-                if (!(r = strdup(s)))
+                r = strdup(s);
+                if (!r)
                         return NULL;
 
-                return strstrip(r);
+                t = strstrip(r);
+                if (t == r)
+                        return r;
+
+                memmove(r, t, strlen(t) + 1);
+                return r;
         }
 
-        if (!(name = strndup(s, p - s)))
+        name = strndup(s, eq - s);
+        if (!name)
                 return NULL;
 
-        if (!(p = strdup(p+1))) {
-                free(name);
+        p = strdup(eq + 1);
+        if (!p)
                 return NULL;
-        }
 
         value = unquote(strstrip(p), QUOTES);
-        free(p);
-
-        if (!value) {
-                free(name);
+        if (!value)
                 return NULL;
-        }
 
-        if (asprintf(&r, "%s=%s", name, value) < 0)
+        if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
                 r = NULL;
 
-        free(value);
-        free(name);
-
         return r;
 }
 
@@ -4011,7 +3967,8 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid) {
         assert(name);
         assert(pid > 1);
 
-        if ((r = wait_for_terminate(pid, &status)) < 0) {
+        r = wait_for_terminate(pid, &status);
+        if (r < 0) {
                 log_warning("Failed to wait for %s: %s", name, strerror(-r));
                 return r;
         }
@@ -4034,7 +3991,6 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid) {
 
         log_warning("%s failed due to unknown reason.", name);
         return -EPROTO;
-
 }
 
 _noreturn_ void freeze(void) {
@@ -4075,10 +4031,12 @@ DIR *xopendirat(int fd, const char *name, int flags) {
         int nfd;
         DIR *d;
 
-        if ((nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags)) < 0)
+        nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
+        if (nfd < 0)
                 return NULL;
 
-        if (!(d = fdopendir(nfd))) {
+        d = fdopendir(nfd);
+        if (!d) {
                 close_nointr_nofail(nfd);
                 return NULL;
         }
@@ -4090,7 +4048,8 @@ int signal_from_string_try_harder(const char *s) {
         int signo;
         assert(s);
 
-        if ((signo = signal_from_string(s)) <= 0)
+        signo = signal_from_string(s);
+        if (signo <= 0)
                 if (startswith(s, "SIG"))
                         return signal_from_string(s+3);
 
@@ -4153,12 +4112,20 @@ static char *tag_to_udev_node(const char *tagvalue, const char *by) {
 }
 
 char *fstab_node_to_udev_node(const char *p) {
+        assert(p);
+
         if (startswith(p, "LABEL="))
                 return tag_to_udev_node(p+6, "label");
 
         if (startswith(p, "UUID="))
                 return tag_to_udev_node(p+5, "uuid");
 
+        if (startswith(p, "PARTUUID="))
+                return tag_to_udev_node(p+9, "partuuid");
+
+        if (startswith(p, "PARTLABEL="))
+                return tag_to_udev_node(p+10, "partlabel");
+
         return strdup(p);
 }
 
@@ -4403,134 +4370,6 @@ bool plymouth_running(void) {
         return access("/run/plymouth/pid", F_OK) >= 0;
 }
 
-void parse_syslog_priority(char **p, int *priority) {
-        int a = 0, b = 0, c = 0;
-        int k;
-
-        assert(p);
-        assert(*p);
-        assert(priority);
-
-        if ((*p)[0] != '<')
-                return;
-
-        if (!strchr(*p, '>'))
-                return;
-
-        if ((*p)[2] == '>') {
-                c = undecchar((*p)[1]);
-                k = 3;
-        } else if ((*p)[3] == '>') {
-                b = undecchar((*p)[1]);
-                c = undecchar((*p)[2]);
-                k = 4;
-        } else if ((*p)[4] == '>') {
-                a = undecchar((*p)[1]);
-                b = undecchar((*p)[2]);
-                c = undecchar((*p)[3]);
-                k = 5;
-        } else
-                return;
-
-        if (a < 0 || b < 0 || c < 0)
-                return;
-
-        *priority = a*100+b*10+c;
-        *p += k;
-}
-
-void skip_syslog_pid(char **buf) {
-        char *p;
-
-        assert(buf);
-        assert(*buf);
-
-        p = *buf;
-
-        if (*p != '[')
-                return;
-
-        p++;
-        p += strspn(p, "0123456789");
-
-        if (*p != ']')
-                return;
-
-        p++;
-
-        *buf = p;
-}
-
-void skip_syslog_date(char **buf) {
-        enum {
-                LETTER,
-                SPACE,
-                NUMBER,
-                SPACE_OR_NUMBER,
-                COLON
-        } sequence[] = {
-                LETTER, LETTER, LETTER,
-                SPACE,
-                SPACE_OR_NUMBER, NUMBER,
-                SPACE,
-                SPACE_OR_NUMBER, NUMBER,
-                COLON,
-                SPACE_OR_NUMBER, NUMBER,
-                COLON,
-                SPACE_OR_NUMBER, NUMBER,
-                SPACE
-        };
-
-        char *p;
-        unsigned i;
-
-        assert(buf);
-        assert(*buf);
-
-        p = *buf;
-
-        for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
-
-                if (!*p)
-                        return;
-
-                switch (sequence[i]) {
-
-                case SPACE:
-                        if (*p != ' ')
-                                return;
-                        break;
-
-                case SPACE_OR_NUMBER:
-                        if (*p == ' ')
-                                break;
-
-                        /* fall through */
-
-                case NUMBER:
-                        if (*p < '0' || *p > '9')
-                                return;
-
-                        break;
-
-                case LETTER:
-                        if (!(*p >= 'A' && *p <= 'Z') &&
-                            !(*p >= 'a' && *p <= 'z'))
-                                return;
-
-                        break;
-
-                case COLON:
-                        if (*p != ':')
-                                return;
-                        break;
-
-                }
-        }
-
-        *buf = p;
-}
-
 char* strshorten(char *s, size_t l) {
         assert(s);
 
@@ -4809,49 +4648,9 @@ int copy_file(const char *from, const char *to) {
         return 0;
 }
 
-int symlink_or_copy(const char *from, const char *to) {
-        char *pf = NULL, *pt = NULL;
-        struct stat a, b;
-        int r;
-
-        assert(from);
-        assert(to);
-
-        if (path_get_parent(from, &pf) < 0 ||
-            path_get_parent(to, &pt) < 0) {
-                r = -ENOMEM;
-                goto finish;
-        }
-
-        if (stat(pf, &a) < 0 ||
-            stat(pt, &b) < 0) {
-                r = -errno;
-                goto finish;
-        }
-
-        if (a.st_dev != b.st_dev) {
-                free(pf);
-                free(pt);
-
-                return copy_file(from, to);
-        }
-
-        if (symlink(from, to) < 0) {
-                r = -errno;
-                goto finish;
-        }
-
-        r = 0;
-
-finish:
-        free(pf);
-        free(pt);
-
-        return r;
-}
-
-int symlink_or_copy_atomic(const char *from, const char *to) {
-        char *t, *x;
+int symlink_atomic(const char *from, const char *to) {
+        char *x;
+        _cleanup_free_ char *t;
         const char *fn;
         size_t k;
         unsigned long long ull;
@@ -4879,22 +4678,16 @@ int symlink_or_copy_atomic(const char *from, const char *to) {
 
         *x = 0;
 
-        r = symlink_or_copy(from, t);
-        if (r < 0) {
-                unlink(t);
-                free(t);
-                return r;
-        }
+        if (symlink(from, t) < 0)
+                return -errno;
 
         if (rename(t, to) < 0) {
                 r = -errno;
                 unlink(t);
-                free(t);
                 return r;
         }
 
-        free(t);
-        return r;
+        return 0;
 }
 
 bool display_is_local(const char *display) {
@@ -5154,10 +4947,11 @@ int get_files_in_directory(const char *path, char ***list) {
                 return -errno;
 
         for (;;) {
-                struct dirent buffer, *de;
+                struct dirent *de;
+                union dirent_storage buf;
                 int k;
 
-                k = readdir_r(d, &buffer, &de);
+                k = readdir_r(d, &buf.de, &de);
                 if (k != 0) {
                         r = -k;
                         goto finish;
@@ -5223,12 +5017,17 @@ char *strjoin(const char *x, ...) {
 
                 for (;;) {
                         const char *t;
+                        size_t n;
 
                         t = va_arg(ap, const char *);
                         if (!t)
                                 break;
 
-                        l += strlen(t);
+                        n = strlen(t);
+                        if (n > ((size_t) -1) - l)
+                                return NULL;
+
+                        l += n;
                 }
         } else
                 l = 0;
@@ -5500,7 +5299,7 @@ int signal_from_string(const char *s) {
         int offset = 0;
         unsigned u;
 
-        signo =__signal_from_string(s);
+        signo = __signal_from_string(s);
         if (signo > 0)
                 return signo;
 
@@ -5821,10 +5620,10 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
 }
 
 int can_sleep(const char *type) {
-        char *p, *w, *state;
+        char *w, *state;
         size_t l, k;
-        bool found = false;
         int r;
+        _cleanup_free_ char *p = NULL;
 
         assert(type);
 
@@ -5833,16 +5632,11 @@ int can_sleep(const char *type) {
                 return r == -ENOENT ? 0 : r;
 
         k = strlen(type);
+        FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
+                if (l == k && memcmp(w, type, l) == 0)
+                        return true;
 
-        FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
-                if (l == k && strncmp(w, type, l) == 0) {
-                        found = true;
-                        break;
-                }
-        }
-
-        free(p);
-        return found;
+        return false;
 }
 
 bool is_valid_documentation_url(const char *url) {
@@ -5867,7 +5661,7 @@ bool is_valid_documentation_url(const char *url) {
 }
 
 bool in_initrd(void) {
-        static int saved = -1;
+        static __thread int saved = -1;
         struct statfs s;
 
         if (saved >= 0)
@@ -5891,13 +5685,13 @@ bool in_initrd(void) {
 }
 
 void warn_melody(void) {
-        int fd;
+        _cleanup_close_ int fd = -1;
 
         fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
         if (fd < 0)
                 return;
 
-        /* Yeah, this is synchronous. Kinda sucks. Bute well... */
+        /* Yeah, this is synchronous. Kinda sucks. But well... */
 
         ioctl(fd, KIOCSOUND, (int)(1193180/440));
         usleep(125*USEC_PER_MSEC);
@@ -5909,7 +5703,6 @@ void warn_melody(void) {
         usleep(125*USEC_PER_MSEC);
 
         ioctl(fd, KIOCSOUND, 0);
-        close_nointr_nofail(fd);
 }
 
 int make_console_stdio(void) {
@@ -5966,7 +5759,7 @@ int get_home_dir(char **_h) {
         errno = 0;
         p = getpwuid(u);
         if (!p)
-                return errno ? -errno : -ENOENT;
+                return errno ? -errno : -ESRCH;
 
         if (!path_is_absolute(p->pw_dir))
                 return -EINVAL;
@@ -6025,3 +5818,26 @@ int get_shell(char **_sh) {
         *_sh = sh;
         return 0;
 }
+
+void freep(void *p) {
+        free(*(void**) p);
+}
+
+void fclosep(FILE **f) {
+        if (*f)
+                fclose(*f);
+}
+
+void closep(int *fd) {
+        if (*fd >= 0)
+                close_nointr_nofail(*fd);
+}
+
+void closedirp(DIR **d) {
+        if (*d)
+                closedir(*d);
+}
+
+void umaskp(mode_t *u) {
+        umask(*u);
+}