chiark / gitweb /
Prep v230: Apply missing upstream fixes and updates (2/8) src/basic.
authorSven Eden <yamakuzure@gmx.net>
Wed, 24 May 2017 11:51:31 +0000 (13:51 +0200)
committerSven Eden <yamakuzure@gmx.net>
Fri, 16 Jun 2017 08:12:58 +0000 (10:12 +0200)
51 files changed:
src/basic/alloc-util.c
src/basic/cgroup-util.c
src/basic/cgroup-util.h
src/basic/copy.c
src/basic/copy.h
src/basic/def.h
src/basic/escape.c
src/basic/escape.h
src/basic/fd-util.c
src/basic/fd-util.h
src/basic/fileio-label.h
src/basic/fileio.c
src/basic/fileio.h
src/basic/fs-util.c
src/basic/fs-util.h
src/basic/hash-funcs.c
src/basic/hash-funcs.h
src/basic/hashmap.c
src/basic/hashmap.h
src/basic/hostname-util.c
src/basic/hostname-util.h
src/basic/log.c
src/basic/log.h
src/basic/login-util.h
src/basic/memfd-util.c
src/basic/memfd-util.h
src/basic/missing.h
src/basic/missing_syscall.h
src/basic/parse-util.c
src/basic/parse-util.h
src/basic/path-util.c
src/basic/path-util.h
src/basic/process-util.c
src/basic/process-util.h
src/basic/rm-rf.c
src/basic/selinux-util.c
src/basic/selinux-util.h
src/basic/siphash24.c
src/basic/socket-util.c
src/basic/socket-util.h
src/basic/stdio-util.h
src/basic/strv.c
src/basic/strv.h
src/basic/terminal-util.c
src/basic/time-util.c
src/basic/time-util.h
src/basic/unit-name.c
src/basic/util.c
src/basic/util.h
src/basic/virt.c
src/basic/virt.h

index a16f97c..b540dcd 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdint.h>
+#include <string.h>
+
 #include "alloc-util.h"
+#include "macro.h"
 #include "util.h"
 
 void* memdup(const void *p, size_t l) {
index 65909f9..3636f13 100644 (file)
@@ -348,7 +348,6 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char
         log_debug_elogind("Migrating \"%s\"/\"%s\" to \"%s\"/\"%s\" (%s)",
                           cfrom, pfrom, cto, pto,
                           ignore_self ? "ignoring self" : "watching self");
-
         do {
                 _cleanup_fclose_ FILE *f = NULL;
                 pid_t pid = 0;
@@ -443,7 +442,7 @@ int cg_migrate_recursive(
                 p = strjoin(pfrom, "/", fn, NULL);
                 free(fn);
                 if (!p)
-                                return -ENOMEM;
+                        return -ENOMEM;
 
                 r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
                 if (r != 0 && ret >= 0)
@@ -527,14 +526,14 @@ static int join_path_legacy(const char *controller, const char *path, const char
                 t = strjoin("/sys/fs/cgroup/", dn, "/", suffix, NULL);
         else if (isempty(suffix))
                 t = strjoin("/sys/fs/cgroup/", dn, "/", path, NULL);
-                else
+        else
                 t = strjoin("/sys/fs/cgroup/", dn, "/", path, "/", suffix, NULL);
         if (!t)
                 return -ENOMEM;
 
         *fs = t;
         return 0;
-        }
+}
 
 static int join_path_unified(const char *path, const char *suffix, char **fs) {
         char *t;
@@ -1068,8 +1067,8 @@ int cg_is_empty_recursive(const char *controller, const char *path) {
                         return r;
 
                 r = cg_enumerate_subgroups(controller, path, &d);
-                        if (r == -ENOENT)
-                                return 1;
+                if (r == -ENOENT)
+                        return 1;
                 if (r < 0)
                         return r;
 
@@ -1294,7 +1293,7 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
 }
 
 #if 0 /// UNNEEDED by elogind
-int cg_path_decode_unit(const char *cgroup, char **unit){
+int cg_path_decode_unit(const char *cgroup, char **unit) {
         char *c, *s;
         size_t n;
 
@@ -1545,9 +1544,7 @@ int cg_pid_get_machine_name(pid_t pid, char **machine) {
 #endif // 0
 
 int cg_path_get_session(const char *path, char **session) {
-        /* Elogind uses a flat hierarchy, just "/SESSION".  The only
-           wrinkle is that SESSION might be escaped.  */
-#if 0
+#if 0 /// UNNEEDED by elogind
         _cleanup_free_ char *unit = NULL;
         char *start, *end;
         int r;
@@ -1569,6 +1566,8 @@ int cg_path_get_session(const char *path, char **session) {
         if (!session_id_valid(start))
                 return -ENXIO;
 #else
+        /* Elogind uses a flat hierarchy, just "/SESSION".  The only
+           wrinkle is that SESSION might be escaped.  */
         const char *e, *n, *start;
 
         assert(path);
@@ -1963,16 +1962,16 @@ int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_m
 
         for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
                 CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
-                        const char *p = NULL;
+                const char *p = NULL;
 
                 if (!(supported & bit))
                         continue;
 
-                        if (path_callback)
-                                p = path_callback(bit, userdata);
+                if (path_callback)
+                        p = path_callback(bit, userdata);
 
-                        if (!p)
-                                p = path;
+                if (!p)
+                        p = path;
 
                 (void) cg_attach_fallback(cgroup_controller_to_string(c), p, pid);
         }
@@ -2015,16 +2014,16 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
 
         for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
                 CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
-                        const char *p = NULL;
+                const char *p = NULL;
 
                 if (!(supported & bit))
                         continue;
 
-                        if (to_callback)
-                                p = to_callback(bit, userdata);
+                if (to_callback)
+                        p = to_callback(bit, userdata);
 
-                        if (!p)
-                                p = to;
+                if (!p)
+                        p = to;
 
                 (void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, false, false);
         }
@@ -2106,12 +2105,12 @@ int cg_mask_supported(CGroupMask *ret) {
                                 continue;
 
                         mask |= CGROUP_CONTROLLER_TO_MASK(v);
-        }
+                }
 
-                /* Currently, we only support the memory and pids
+                /* Currently, we only support the memory, io and pids
                  * controller in the unified hierarchy, mask
                  * everything else off. */
-                mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_PIDS;
+                mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS;
 
         } else {
                 CGroupController c;
@@ -2206,21 +2205,21 @@ int cg_unified(void) {
         if (statfs("/sys/fs/cgroup/", &fs) < 0)
                 return -errno;
 
-/// elogind can not support the unified hierarchy as a controller,
-/// so always assume a classical hierarchy.
-/// If, ond only *if*, someone really wants to substitute systemd-login
-/// in an environment managed by systemd with elogin, we might have to
-/// add such a support.
-#if 0
-        if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC))
+#if 0 /// UNNEEDED by elogind
+        if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC))
                 unified_cache = true;
         else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
 #else
+        /* elogind can not support the unified hierarchy as a controller,
+         * so always assume a classical hierarchy.
+         * If, ond only *if*, someone really wants to substitute systemd-login
+         * in an environment managed by systemd with elogin, we might have to
+         * add such a support. */
         if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
 #endif // 0
                 unified_cache = false;
         else
-                return -ENOEXEC;
+                return -ENOMEDIUM;
 
         return unified_cache;
 }
@@ -2315,6 +2314,42 @@ bool cg_is_legacy_wanted(void) {
 #endif // 0
 
 #if 0 /// UNNEEDED by elogind
+int cg_weight_parse(const char *s, uint64_t *ret) {
+        uint64_t u;
+        int r;
+
+        if (isempty(s)) {
+                *ret = CGROUP_WEIGHT_INVALID;
+                return 0;
+        }
+
+        r = safe_atou64(s, &u);
+        if (r < 0)
+                return r;
+
+        if (u < CGROUP_WEIGHT_MIN || u > CGROUP_WEIGHT_MAX)
+                return -ERANGE;
+
+        *ret = u;
+        return 0;
+}
+
+const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX] = {
+        [CGROUP_IO_RBPS_MAX]    = CGROUP_LIMIT_MAX,
+        [CGROUP_IO_WBPS_MAX]    = CGROUP_LIMIT_MAX,
+        [CGROUP_IO_RIOPS_MAX]   = CGROUP_LIMIT_MAX,
+        [CGROUP_IO_WIOPS_MAX]   = CGROUP_LIMIT_MAX,
+};
+
+static const char* const cgroup_io_limit_type_table[_CGROUP_IO_LIMIT_TYPE_MAX] = {
+        [CGROUP_IO_RBPS_MAX]    = "IOReadBandwidthMax",
+        [CGROUP_IO_WBPS_MAX]    = "IOWriteBandwidthMax",
+        [CGROUP_IO_RIOPS_MAX]   = "IOReadIOPSMax",
+        [CGROUP_IO_WIOPS_MAX]   = "IOWriteIOPSMax",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(cgroup_io_limit_type, CGroupIOLimitType);
+
 int cg_cpu_shares_parse(const char *s, uint64_t *ret) {
         uint64_t u;
         int r;
@@ -2359,6 +2394,7 @@ int cg_blkio_weight_parse(const char *s, uint64_t *ret) {
 static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
         [CGROUP_CONTROLLER_CPU] = "cpu",
         [CGROUP_CONTROLLER_CPUACCT] = "cpuacct",
+        [CGROUP_CONTROLLER_IO] = "io",
         [CGROUP_CONTROLLER_BLKIO] = "blkio",
         [CGROUP_CONTROLLER_MEMORY] = "memory",
         [CGROUP_CONTROLLER_DEVICES] = "devices",
index 996fe59..2ff4384 100644 (file)
@@ -34,6 +34,7 @@
 typedef enum CGroupController {
         CGROUP_CONTROLLER_CPU,
         CGROUP_CONTROLLER_CPUACCT,
+        CGROUP_CONTROLLER_IO,
         CGROUP_CONTROLLER_BLKIO,
         CGROUP_CONTROLLER_MEMORY,
         CGROUP_CONTROLLER_DEVICES,
@@ -48,6 +49,7 @@ typedef enum CGroupController {
 typedef enum CGroupMask {
         CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU),
         CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT),
+        CGROUP_MASK_IO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_IO),
         CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO),
         CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY),
         CGROUP_MASK_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_DEVICES),
@@ -56,6 +58,37 @@ typedef enum CGroupMask {
 } CGroupMask;
 
 #if 0 /// UNNEEDED by elogind
+/* Special values for all weight knobs on unified hierarchy */
+#define CGROUP_WEIGHT_INVALID ((uint64_t) -1)
+#define CGROUP_WEIGHT_MIN UINT64_C(1)
+#define CGROUP_WEIGHT_MAX UINT64_C(10000)
+#define CGROUP_WEIGHT_DEFAULT UINT64_C(100)
+
+#define CGROUP_LIMIT_MIN UINT64_C(0)
+#define CGROUP_LIMIT_MAX ((uint64_t) -1)
+
+static inline bool CGROUP_WEIGHT_IS_OK(uint64_t x) {
+        return
+            x == CGROUP_WEIGHT_INVALID ||
+            (x >= CGROUP_WEIGHT_MIN && x <= CGROUP_WEIGHT_MAX);
+}
+
+/* IO limits on unified hierarchy */
+typedef enum CGroupIOLimitType {
+        CGROUP_IO_RBPS_MAX,
+        CGROUP_IO_WBPS_MAX,
+        CGROUP_IO_RIOPS_MAX,
+        CGROUP_IO_WIOPS_MAX,
+
+        _CGROUP_IO_LIMIT_TYPE_MAX,
+        _CGROUP_IO_LIMIT_TYPE_INVALID = -1
+} CGroupIOLimitType;
+
+extern const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX];
+
+const char* cgroup_io_limit_type_to_string(CGroupIOLimitType t) _const_;
+CGroupIOLimitType cgroup_io_limit_type_from_string(const char *s) _pure_;
+
 /* Special values for the cpu.shares attribute */
 #define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1)
 #define CGROUP_CPU_SHARES_MIN UINT64_C(2)
@@ -135,6 +168,7 @@ int cg_get_attribute(const char *controller, const char *path, const char *attri
 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
 #endif // 0
+
 int cg_install_release_agent(const char *controller, const char *agent);
 int cg_uninstall_release_agent(const char *controller);
 
@@ -152,6 +186,7 @@ int cg_path_get_machine_name(const char *path, char **machine);
 int cg_path_get_slice(const char *path, char **slice);
 int cg_path_get_user_slice(const char *path, char **slice);
 #endif // 0
+
 int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted);
 int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup);
 
@@ -166,10 +201,12 @@ int cg_pid_get_user_slice(pid_t pid, char **slice);
 
 int cg_path_decode_unit(const char *cgroup, char **unit);
 #endif // 0
+
 char *cg_escape(const char *p);
 char *cg_unescape(const char *p) _pure_;
 
 bool cg_controller_is_valid(const char *p);
+
 #if 0 /// UNNEEDED by elogind
 int cg_slice_to_path(const char *unit, char **ret);
 
@@ -182,10 +219,13 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
 int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root);
 int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p);
 #endif // 0
+
 int cg_mask_supported(CGroupMask *ret);
+
 #if 0 /// UNNEEDED by elogind
 int cg_kernel_controllers(Set *controllers);
 #endif // 0
+
 int cg_unified(void);
 #if 0 /// UNNEEDED by elogind
 void cg_unified_flush(void);
@@ -196,7 +236,9 @@ bool cg_is_legacy_wanted(void);
 
 const char* cgroup_controller_to_string(CGroupController c) _const_;
 CGroupController cgroup_controller_from_string(const char *s) _pure_;
+
 #if 0 /// UNNEEDED by elogind
+int cg_weight_parse(const char *s, uint64_t *ret);
 int cg_cpu_shares_parse(const char *s, uint64_t *ret);
 int cg_blkio_weight_parse(const char *s, uint64_t *ret);
 #endif // 0
index c2c0579..66279cf 100644 (file)
 //#include "umask-util.h"
 //#include "xattr-util.h"
 
-#define COPY_BUFFER_SIZE (16*1024)
+#define COPY_BUFFER_SIZE (16*1024u)
+
+static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
+                                   int fd_out, loff_t *off_out,
+                                   size_t len,
+                                   unsigned int flags) {
+        static int have = -1;
+        ssize_t r;
+
+        if (have == false)
+                return -ENOSYS;
+
+        r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
+        if (_unlikely_(have < 0))
+                have = r >= 0 || errno != ENOSYS;
+        if (r >= 0)
+                return r;
+        else
+                return -errno;
+}
 
 int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
-        bool try_sendfile = true, try_splice = true;
+        bool try_cfr = true, try_sendfile = true, try_splice = true;
         int r;
+        size_t m = SSIZE_MAX; /* that is the maximum that sendfile and c_f_r accept */
 
         assert(fdf >= 0);
         assert(fdt >= 0);
+
 #if 0 /// UNNEEDED by elogind
         /* Try btrfs reflinks first. */
         if (try_reflink &&
@@ -66,57 +87,71 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
                         return 0; /* we copied the whole thing, hence hit EOF, return 0 */
         }
 #endif // 0
+
         for (;;) {
-                size_t m = COPY_BUFFER_SIZE;
                 ssize_t n;
 
                 if (max_bytes != (uint64_t) -1) {
-
                         if (max_bytes <= 0)
                                 return 1; /* return > 0 if we hit the max_bytes limit */
 
-                        if ((uint64_t) m > max_bytes)
-                                m = (size_t) max_bytes;
+                        if (m > max_bytes)
+                                m = max_bytes;
+                }
+
+                /* First try copy_file_range(), unless we already tried */
+                if (try_cfr) {
+                        n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
+                        if (n < 0) {
+                                if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV, -EBADF))
+                                        return n;
+
+                                try_cfr = false;
+                                /* use fallback below */
+                        } else if (n == 0) /* EOF */
+                                break;
+                        else
+                                /* Success! */
+                                goto next;
                 }
 
                 /* First try sendfile(), unless we already tried */
                 if (try_sendfile) {
-
                         n = sendfile(fdt, fdf, NULL, m);
                         if (n < 0) {
-                                if (errno != EINVAL && errno != ENOSYS)
+                                if (!IN_SET(errno, EINVAL, ENOSYS))
                                         return -errno;
 
                                 try_sendfile = false;
                                 /* use fallback below */
                         } else if (n == 0) /* EOF */
                                 break;
-                        else if (n > 0)
+                        else
                                 /* Success! */
                                 goto next;
                 }
 
-                /* The try splice, unless we already tried */
+                /* Then try splice, unless we already tried */
                 if (try_splice) {
-                        n  = splice(fdf, NULL, fdt, NULL, m, 0);
+                        n = splice(fdf, NULL, fdt, NULL, m, 0);
                         if (n < 0) {
-                                if (errno != EINVAL && errno != ENOSYS)
+                                if (!IN_SET(errno, EINVAL, ENOSYS))
                                         return -errno;
 
                                 try_splice = false;
                                 /* use fallback below */
                         } else if (n == 0) /* EOF */
                                 break;
-                        else if (n > 0)
+                        else
                                 /* Success! */
                                 goto next;
                 }
 
                 /* As a fallback just copy bits by hand */
                 {
-                        uint8_t buf[m];
+                        uint8_t buf[MIN(m, COPY_BUFFER_SIZE)];
 
-                        n = read(fdf, buf, m);
+                        n = read(fdf, buf, sizeof buf);
                         if (n < 0)
                                 return -errno;
                         if (n == 0) /* EOF */
@@ -132,6 +167,11 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
                         assert(max_bytes >= (uint64_t) n);
                         max_bytes -= n;
                 }
+                /* sendfile accepts at most SSIZE_MAX-offset bytes to copy,
+                 * so reduce our maximum by the amount we already copied,
+                 * but don't go below our copy buffer size, unless we are
+                 * close the the limit of bytes we are allowed to copy. */
+                m = MAX(MIN(COPY_BUFFER_SIZE, max_bytes), m - n);
         }
 
         return 0; /* return 0 if we hit EOF earlier than the size limit */
index c389724..41aad74 100644 (file)
@@ -31,6 +31,7 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace
 int copy_tree(const char *from, const char *to, bool merge);
 int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge);
 int copy_directory_fd(int dirfd, const char *to, bool merge);
+int copy_directory(const char *from, const char *to, bool merge);
 #endif // 0
 int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink);
 #if 0 /// UNNEEDED by elogind
index 31753e6..bc7826f 100644 (file)
@@ -40,8 +40,6 @@
 #define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
 #define SIGNALS_IGNORE SIGPIPE
 
-#define REBOOT_PARAM_FILE "/run/systemd/reboot-param"
-
 #ifdef HAVE_SPLIT_USR
 #define KBD_KEYMAP_DIRS                         \
         "/usr/share/keymaps/\0"                 \
index 5641493..127ca2e 100644 (file)
@@ -414,6 +414,34 @@ char *xescape(const char *s, const char *bad) {
 }
 
 #if 0 /// UNNEEDED by elogind
+char *octescape(const char *s, size_t len) {
+        char *r, *t;
+        const char *f;
+
+        /* Escapes all chars in bad, in addition to \ and " chars,
+         * in \nnn style escaping. */
+
+        r = new(char, len * 4 + 1);
+        if (!r)
+                return NULL;
+
+        for (f = s, t = r; f < s + len; f++) {
+
+                if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') {
+                        *(t++) = '\\';
+                        *(t++) = '0' + (*f >> 6);
+                        *(t++) = '0' + ((*f >> 3) & 8);
+                        *(t++) = '0' + (*f & 8);
+                } else
+                        *(t++) = *f;
+        }
+
+        *t = 0;
+
+        return r;
+
+}
+
 static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
         assert(bad);
 
index f574380..8383c75 100644 (file)
@@ -48,8 +48,9 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
 int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
 
 char *xescape(const char *s, const char *bad);
-
 #if 0 /// UNNEEDED by elogind
+char *octescape(const char *s, size_t len);
+
 char *shell_escape(const char *s, const char *bad);
 char *shell_maybe_quote(const char *s);
 #endif // 0
index 9c15b91..8e4cfe3 100644 (file)
@@ -359,4 +359,18 @@ bool fdname_is_valid(const char *s) {
 
         return p - s < 256;
 }
+
+int fd_get_path(int fd, char **ret) {
+        char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+        int r;
+
+        xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+
+        r = readlink_malloc(procfs_path, ret);
+
+        if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */
+                return -EBADF;
+
+        return r;
+}
 #endif // 0
index e2f5bbd..522ea68 100644 (file)
@@ -74,6 +74,8 @@ int same_fd(int a, int b);
 void cmsg_close_all(struct msghdr *mh);
 
 bool fdname_is_valid(const char *s);
+
+int fd_get_path(int fd, char **ret);
 #endif // 0
 
 /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
index 25262ef..4deeef2 100644 (file)
@@ -25,7 +25,6 @@
 #include "fileio.h"
 
 int write_string_file_atomic_label(const char *fn, const char *line);
-
 #if 0 /// UNNEEDED by elogind
 int write_env_file_label(const char *fname, char **l);
 int fopen_temporary_label(const char *target,
index da53c3e..d3fb861 100644 (file)
@@ -880,13 +880,13 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
 
                 do {
                         t = strstr(t, pattern);
-        if (!t)
-                return -ENOENT;
+                        if (!t)
+                                return -ENOENT;
 
                         /* Check that pattern occurs in beginning of line. */
                         pattern_ok = (t == status || t[-1] == '\n');
 
-        t += strlen(pattern);
+                        t += strlen(pattern);
 
                 } while (!pattern_ok);
 
@@ -1087,32 +1087,6 @@ int mkostemp_safe(char *pattern, int flags) {
         return fd;
 }
 
-#if 0 /// UNNEEDED by elogind
-int open_tmpfile(const char *path, int flags) {
-        char *p;
-        int fd;
-
-        assert(path);
-
-#ifdef O_TMPFILE
-        /* Try O_TMPFILE first, if it is supported */
-        fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
-        if (fd >= 0)
-                return fd;
-#endif
-
-        /* Fall back to unguessable name + unlinking */
-        p = strjoina(path, "/systemd-tmp-XXXXXX");
-
-        fd = mkostemp_safe(p, flags);
-        if (fd < 0)
-                return fd;
-
-        unlink(p);
-        return fd;
-}
-#endif // 0
-
 int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
         const char *fn;
         char *t;
@@ -1145,7 +1119,6 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
         return 0;
 }
 
-#if 0 /// UNNEEDED by elogind
 int tempfn_random(const char *p, const char *extra, char **ret) {
         const char *fn;
         char *t, *x;
@@ -1188,6 +1161,7 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
         return 0;
 }
 
+#if 0 /// UNNEEDED by elogind
 int tempfn_random_child(const char *p, const char *extra, char **ret) {
         char *t, *x;
         uint64_t u;
@@ -1285,4 +1259,104 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space)
 
         return fputs(s, f);
 }
+
+int open_tmpfile_unlinkable(const char *directory, int flags) {
+        char *p;
+        int fd;
+
+        assert(directory);
+
+        /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
+
+#ifdef O_TMPFILE
+        /* Try O_TMPFILE first, if it is supported */
+        fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
+        if (fd >= 0)
+                return fd;
+#endif
+
+        /* Fall back to unguessable name + unlinking */
+        p = strjoina(directory, "/systemd-tmp-XXXXXX");
+
+        fd = mkostemp_safe(p, flags);
+        if (fd < 0)
+                return fd;
+
+        (void) unlink(p);
+
+        return fd;
+}
+
+int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
+        _cleanup_free_ char *tmp = NULL;
+        int r, fd;
+
+        assert(target);
+        assert(ret_path);
+
+        /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
+        assert((flags & O_EXCL) == 0);
+
+        /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
+         * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
+         * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
+
+#ifdef O_TMPFILE
+        {
+                _cleanup_free_ char *dn = NULL;
+
+                dn = dirname_malloc(target);
+                if (!dn)
+                        return -ENOMEM;
+
+                fd = open(dn, O_TMPFILE|flags, 0640);
+                if (fd >= 0) {
+                        *ret_path = NULL;
+                        return fd;
+                }
+
+                log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
+        }
+#endif
+
+        r = tempfn_random(target, NULL, &tmp);
+        if (r < 0)
+                return r;
+
+        fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640);
+        if (fd < 0)
+                return -errno;
+
+        *ret_path = tmp;
+        tmp = NULL;
+
+        return fd;
+}
+
+int link_tmpfile(int fd, const char *path, const char *target) {
+
+        assert(fd >= 0);
+        assert(target);
+
+        /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
+         * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
+         * on the directory, and renameat2() is used instead.
+         *
+         * Note that in both cases we will not replace existing files. This is because linkat() does not support this
+         * operation currently (renameat2() does), and there is no nice way to emulate this. */
+
+        if (path) {
+                if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
+                        return -errno;
+        } else {
+                char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
+
+                xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
+
+                if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0)
+                        return -errno;
+        }
+
+        return 0;
+}
 #endif // 0
index 0635147..3c7b9c8 100644 (file)
@@ -62,6 +62,7 @@ DIR *xopendirat(int dirfd, const char *name, int flags);
 int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
 int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
 #endif // 0
+
 #define FOREACH_LINE(line, f, on_error)                         \
         for (;;)                                                \
                 if (!fgets(line, sizeof(line), f)) {            \
@@ -75,17 +76,19 @@ int fflush_and_check(FILE *f);
 
 int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
 int mkostemp_safe(char *pattern, int flags);
-#if 0 /// UNNEEDED by elogind
-int open_tmpfile(const char *path, int flags);
-#endif // 0
 
 int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
-#if 0 /// UNNEEDED by elogind
 int tempfn_random(const char *p, const char *extra, char **ret);
+#if 0 /// UNNEEDED by elogind
 int tempfn_random_child(const char *p, const char *extra, char **ret);
 
 int write_timestamp_file_atomic(const char *fn, usec_t n);
 int read_timestamp_file(const char *fn, usec_t *ret);
 
 int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
+
+int open_tmpfile_unlinkable(const char *directory, int flags);
+int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
+
+int link_tmpfile(int fd, const char *path, const char *target);
 #endif // 0
index b37fef8..426ad97 100644 (file)
@@ -287,26 +287,6 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
         return 0;
 }
 
-#if 0 /// UNNEEDED by elogind
-int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
-        assert(fd >= 0);
-
-        /* Under the assumption that we are running privileged we
-         * first change the access mode and only then hand out
-         * ownership to avoid a window where access is too open. */
-
-        if (mode != MODE_INVALID)
-                if (fchmod(fd, mode) < 0)
-                        return -errno;
-
-        if (uid != UID_INVALID || gid != GID_INVALID)
-                if (fchown(fd, uid, gid) < 0)
-                        return -errno;
-
-        return 0;
-}
-#endif // 0
-
 int fchmod_umask(int fd, mode_t m) {
         mode_t u;
         int r;
@@ -519,3 +499,19 @@ int get_files_in_directory(const char *path, char ***list) {
 
         return n;
 }
+
+#if 0 /// UNNEEDED by elogind
+int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
+        char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
+        int r;
+
+        /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
+        xsprintf(path, "/proc/self/fd/%i", what);
+
+        r = inotify_add_watch(fd, path, mask);
+        if (r < 0)
+                return -errno;
+
+        return r;
+}
+#endif // 0
index 2000b38..2c5a650 100644 (file)
 #include "time-util.h"
 
 int unlink_noerrno(const char *path);
+
 #if 0 /// UNNEEDED by elogind
 int rmdir_parents(const char *path, const char *stop);
 
 int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
 #endif // 0
+
 int readlinkat_malloc(int fd, const char *p, char **ret);
 int readlink_malloc(const char *p, char **r);
 #if 0 /// UNNEEDED by elogind
@@ -43,10 +45,9 @@ int readlink_and_make_absolute(const char *p, char **r);
 int readlink_and_canonicalize(const char *p, char **r);
 int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
 #endif // 0
+
 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
-#if 0 /// UNNEEDED by elogind
-int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
-#endif // 0
+
 int fchmod_umask(int fd, mode_t mode);
 
 int fd_warn_permissions(const char *path, int fd);
@@ -60,6 +61,7 @@ int fd_warn_permissions(const char *path, int fd);
 
 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
 int touch(const char *path);
+
 #if 0 /// UNNEEDED by elogind
 int symlink_idempotent(const char *from, const char *to);
 
@@ -67,6 +69,7 @@ int symlink_atomic(const char *from, const char *to);
 int mknod_atomic(const char *path, mode_t mode, dev_t dev);
 int mkfifo_atomic(const char *path, mode_t mode);
 #endif // 0
+
 int get_files_in_directory(const char *path, char ***list);
 
 #if 0 /// UNNEEDED by elogind
@@ -81,4 +84,6 @@ union inotify_event_buffer {
         struct inotify_event ev;
         uint8_t raw[INOTIFY_EVENT_MAX];
 };
+
+int inotify_add_watch_fd(int fd, int what, uint32_t mask);
 #endif // 0
index d7b61ce..c3a4a01 100644 (file)
@@ -1,21 +1,21 @@
 /***
-  This file is part of elogind.
+  This file is part of systemd.
 
   Copyright 2010 Lennart Poettering
   Copyright 2014 Michal Schmidt
 
-  elogind is free software; you can redistribute it and/or modify it
+  systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2.1 of the License, or
   (at your option) any later version.
 
-  elogind is distributed in the hope that it will be useful, but
+  systemd is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
 #include "hash-funcs.h"
index 01be3ca..299189d 100644 (file)
@@ -1,23 +1,23 @@
 #pragma once
 
 /***
-  This file is part of elogind.
+  This file is part of systemd.
 
   Copyright 2010 Lennart Poettering
   Copyright 2014 Michal Schmidt
 
-  elogind is free software; you can redistribute it and/or modify it
+  systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2.1 of the License, or
   (at your option) any later version.
 
-  elogind is distributed in the hope that it will be useful, but
+  systemd is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
 #include "macro.h"
index 75ea2e3..c89630f 100644 (file)
@@ -1777,20 +1777,18 @@ int set_consume(Set *s, void *value) {
 
 int set_put_strdup(Set *s, const char *p) {
         char *c;
-        int r;
 
         assert(s);
         assert(p);
 
+        if (set_contains(s, (char*) p))
+                return 0;
+
         c = strdup(p);
         if (!c)
                 return -ENOMEM;
 
-        r = set_consume(s, c);
-        if (r == -EEXIST)
-                return 0;
-
-        return r;
+        return set_consume(s, c);
 }
 
 #if 0 /// UNNEEDED by elogind
index a510272..0fda53e 100644 (file)
@@ -327,10 +327,12 @@ static inline void *hashmap_first(Hashmap *h) {
 static inline void *ordered_hashmap_first(OrderedHashmap *h) {
         return internal_hashmap_first(HASHMAP_BASE(h));
 }
+
 #if 0 /// UNNEEDED by elogind
 /* no hashmap_next */
 void *ordered_hashmap_next(OrderedHashmap *h, const void *key);
 #endif // 0
+
 char **internal_hashmap_get_strv(HashmapBase *h);
 static inline char **hashmap_get_strv(Hashmap *h) {
         return internal_hashmap_get_strv(HASHMAP_BASE(h));
index 3bd3a4d..d8d05df 100644 (file)
@@ -17,9 +17,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#if defined(__GLIBC__)
-# include <bits/local_lim.h>
-#endif // defined(__GLIBC__)
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
@@ -52,6 +49,10 @@ bool hostname_is_set(void) {
 char* gethostname_malloc(void) {
         struct utsname u;
 
+        /* This call tries to return something useful, either the actual hostname
+         * or it makes something up. The only reason it might fail is OOM.
+         * It might even return "localhost" if that's set. */
+
         assert_se(uname(&u) >= 0);
 
         if (isempty(u.nodename) || streq(u.nodename, "(none)"))
@@ -59,6 +60,31 @@ char* gethostname_malloc(void) {
 
         return strdup(u.nodename);
 }
+
+int gethostname_strict(char **ret) {
+        struct utsname u;
+        char *k;
+
+        /* This call will rather fail than make up a name. It will not return "localhost" either. */
+
+        assert_se(uname(&u) >= 0);
+
+        if (isempty(u.nodename))
+                return -ENXIO;
+
+        if (streq(u.nodename, "(none)"))
+                return -ENXIO;
+
+        if (is_localhost(u.nodename))
+                return -ENXIO;
+
+        k = strdup(u.nodename);
+        if (!k)
+                return -ENOMEM;
+
+        *ret = k;
+        return 0;
+}
 #endif // 0
 
 static bool hostname_valid_char(char c) {
@@ -127,6 +153,8 @@ char* hostname_cleanup(char *s) {
 
         assert(s);
 
+        strshorten(s, HOST_NAME_MAX);
+
         for (p = s, d = s, dot = true; *p; p++) {
                 if (*p == '.') {
                         if (dot)
@@ -146,8 +174,6 @@ char* hostname_cleanup(char *s) {
         else
                 *d = 0;
 
-        strshorten(s, HOST_NAME_MAX);
-
         return s;
 }
 #endif // 0
@@ -156,16 +182,16 @@ bool is_localhost(const char *hostname) {
         assert(hostname);
 
         /* This tries to identify local host and domain names
-         * described in RFC6761 plus the redhatism of .localdomain */
+         * described in RFC6761 plus the redhatism of localdomain */
 
         return strcaseeq(hostname, "localhost") ||
                strcaseeq(hostname, "localhost.") ||
-               strcaseeq(hostname, "localdomain.") ||
-               strcaseeq(hostname, "localdomain") ||
+               strcaseeq(hostname, "localhost.localdomain") ||
+               strcaseeq(hostname, "localhost.localdomain.") ||
                endswith_no_case(hostname, ".localhost") ||
                endswith_no_case(hostname, ".localhost.") ||
-               endswith_no_case(hostname, ".localdomain") ||
-               endswith_no_case(hostname, ".localdomain.");
+               endswith_no_case(hostname, ".localhost.localdomain") ||
+               endswith_no_case(hostname, ".localhost.localdomain.");
 }
 
 #if 0 /// UNNEEDED by elogind
index f22716d..1c9efab 100644 (file)
@@ -27,7 +27,9 @@
 bool hostname_is_set(void);
 
 char* gethostname_malloc(void);
+int gethostname_strict(char **ret);
 #endif // 0
+
 bool hostname_is_valid(const char *s, bool allow_trailing_dot) _pure_;
 #if 0 /// UNNEEDED by elogind
 char* hostname_cleanup(char *s);
index 08aa986..1b8374c 100644 (file)
@@ -71,7 +71,9 @@ static bool syslog_is_stream = false;
 static bool show_color = false;
 static bool show_location = false;
 
-/// UNNEEDED by elogind  static bool upgrade_syslog_to_journal = false;
+#if 0 /// UNNEEDED by elogind
+static bool upgrade_syslog_to_journal = false;
+#endif // 0
 
 /* Akin to glibc's __abort_msg; which is private and we hence cannot
  * use here. */
@@ -193,11 +195,13 @@ fail:
         return r;
 }
 
-#if 0 /// UNNEEDED by elogind
 void log_close_journal(void) {
+#if 0 /// elogind does not support journald
         journal_fd = safe_close(journal_fd);
+#endif // 0
 }
 
+#if 0 /// UNNEEDED by elogind
 static int log_open_journal(void) {
 
         static const union sockaddr_union sa = {
@@ -239,7 +243,7 @@ int log_open(void) {
          * because there is no reason to close it. */
 
         if (log_target == LOG_TARGET_NULL) {
-                /// UNNEEDED by elogind log_close_journal();
+                log_close_journal();
                 log_close_syslog();
                 log_close_console();
                 return 0;
@@ -261,11 +265,12 @@ int log_open(void) {
                         }
                 }
 #endif // 0
+
                 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
                     log_target == LOG_TARGET_SYSLOG) {
                         r = log_open_syslog();
                         if (r >= 0) {
-                                /// UNNEEDED by elogind log_close_journal();
+                                log_close_journal();
                                 log_close_console();
                                 return r;
                         }
@@ -273,12 +278,12 @@ int log_open(void) {
 
                 if (log_target == LOG_TARGET_AUTO ||
                     log_target == LOG_TARGET_SAFE ||
-                    /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
+                    log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
                     log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
                     log_target == LOG_TARGET_KMSG) {
                         r = log_open_kmsg();
                         if (r >= 0) {
-                                /// UNNEEDED by elogind log_close_journal();
+                                log_close_journal();
                                 log_close_syslog();
                                 log_close_console();
                                 return r;
@@ -286,7 +291,7 @@ int log_open(void) {
                 }
         }
 
-        /// UNNEEDED by elogind log_close_journal();
+        log_close_journal();
         log_close_syslog();
 
         return log_open_console();
@@ -309,7 +314,7 @@ void log_set_target(LogTarget target) {
 }
 
 void log_close(void) {
-        /// UNNEDED by elogind log_close_journal();
+        log_close_journal();
         log_close_syslog();
         log_close_kmsg();
         log_close_console();
@@ -623,7 +628,7 @@ static int log_dispatch(
                     (log_target == LOG_TARGET_AUTO ||
                      log_target == LOG_TARGET_SAFE ||
                      log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
-                     /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
+                     log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
                      log_target == LOG_TARGET_KMSG)) {
 
                         k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
index 899474d..0b82b76 100644 (file)
@@ -35,10 +35,8 @@ typedef enum LogTarget{
         LOG_TARGET_CONSOLE,
         LOG_TARGET_CONSOLE_PREFIXED,
         LOG_TARGET_KMSG,
-#if 0 /// elogind does not support logging to systemd-journald
         LOG_TARGET_JOURNAL,
         LOG_TARGET_JOURNAL_OR_KMSG,
-#endif // 0
         LOG_TARGET_SYSLOG,
         LOG_TARGET_SYSLOG_OR_KMSG,
         LOG_TARGET_AUTO, /* console if stderr is tty, JOURNAL_OR_KMSG otherwise */
@@ -71,10 +69,9 @@ void log_close(void);
 #if 0 /// UNNEEDED by elogind
 void log_forget_fds(void);
 #endif // 0
+
 void log_close_syslog(void);
-#if 0 /// UNNEEDED by elogind
 void log_close_journal(void);
-#endif // 0
 void log_close_kmsg(void);
 void log_close_console(void);
 
@@ -198,13 +195,13 @@ void log_assert_failed_return(
 #ifdef LOG_TRACE
 #  define log_trace(...) log_debug(__VA_ARGS__)
 #else
-#  define log_trace(...) do {} while(0)
+#  define log_trace(...) do {} while (0)
 #endif
 
 #ifdef ENABLE_DEBUG_ELOGIND
 #  define log_debug_elogind(...) log_debug(__VA_ARGS__);usleep(25*USEC_PER_MSEC)
 #else
-#  define log_debug_elogind(...) do {} while(0)
+#  define log_debug_elogind(...) do {} while (0)
 #endif // ENABLE_DEBUG_ELOGIND
 
 /* Structured logging */
index 89a337d..b01ee25 100644 (file)
@@ -1,3 +1,5 @@
+#pragma once
+
 /***
   This file is part of systemd.
 
@@ -17,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#pragma once
-
 #include <stdbool.h>
 #include <unistd.h>
 
index 66b5e5c..e857c04 100644 (file)
@@ -22,7 +22,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #ifdef HAVE_LINUX_MEMFD_H
-#  include <linux/memfd.h>
+#include <linux/memfd.h>
 #endif
 #include <stdio.h>
 #include <sys/mman.h>
index 419d899..6b82852 100644 (file)
@@ -30,6 +30,7 @@ int memfd_new_and_map(const char *name, size_t sz, void **p);
 
 int memfd_map(int fd, uint64_t offset, size_t size, void **p);
 #endif // 0
+
 int memfd_set_sealed(int fd);
 #if 0 /// UNNEEDED by elogind
 int memfd_get_sealed(int fd);
index 7948fc1..984a4c0 100644 (file)
 #define SOL_SCTP 132
 #endif
 
-#if !HAVE_DECL_PIVOT_ROOT
-static inline int pivot_root(const char *new_root, const char *put_old) {
-        return syscall(SYS_pivot_root, new_root, put_old);
-}
-#endif
-
-#ifndef __NR_memfd_create
-#  if defined __x86_64__
-#    define __NR_memfd_create 319
-#  elif defined __arm__
-#    define __NR_memfd_create 385
-#  elif defined __aarch64__
-#    define __NR_memfd_create 279
-#  elif defined __s390__
-#    define __NR_memfd_create 350
-#  elif defined _MIPS_SIM
-#    if _MIPS_SIM == _MIPS_SIM_ABI32
-#      define __NR_memfd_create 4354
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_NABI32
-#      define __NR_memfd_create 6318
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_ABI64
-#      define __NR_memfd_create 5314
-#    endif
-#  elif defined __i386__
-#    define __NR_memfd_create 356
-#  else
-#    warning "__NR_memfd_create unknown for your architecture"
-#    define __NR_memfd_create 0xffffffff
-#  endif
-#endif
-
-#if !HAVE_DECL_MEMFD_CREATE
-static inline int memfd_create(const char *name, unsigned int flags) {
-        return syscall(__NR_memfd_create, name, flags);
-}
-#endif
-
-#ifndef __NR_getrandom
-#  if defined __x86_64__
-#    define __NR_getrandom 318
-#  elif defined(__i386__)
-#    define __NR_getrandom 355
-#  elif defined(__arm__)
-#    define __NR_getrandom 384
-# elif defined(__aarch64__)
-#    define __NR_getrandom 278
-#  elif defined(__ia64__)
-#    define __NR_getrandom 1339
-#  elif defined(__m68k__)
-#    define __NR_getrandom 352
-#  elif defined(__s390x__)
-#    define __NR_getrandom 349
-#  elif defined(__powerpc__)
-#    define __NR_getrandom 359
-#  elif defined _MIPS_SIM
-#    if _MIPS_SIM == _MIPS_SIM_ABI32
-#      define __NR_getrandom 4353
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_NABI32
-#      define __NR_getrandom 6317
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_ABI64
-#      define __NR_getrandom 5313
-#    endif
-#  else
-#    warning "__NR_getrandom unknown for your architecture"
-#    define __NR_getrandom 0xffffffff
-#  endif
-#endif
-
-#if !HAVE_DECL_GETRANDOM
-static inline int getrandom(void *buffer, size_t count, unsigned flags) {
-        return syscall(__NR_getrandom, buffer, count, flags);
-}
-#endif
-
 #ifndef GRND_NONBLOCK
 #define GRND_NONBLOCK 0x0001
 #endif
@@ -544,12 +466,6 @@ struct btrfs_ioctl_quota_ctl_args {
 #define MS_PRIVATE  (1 << 18)
 #endif
 
-#if !HAVE_DECL_GETTID
-static inline pid_t gettid(void) {
-        return (pid_t) syscall(SYS_gettid);
-}
-#endif
-
 #ifndef SCM_SECURITY
 #define SCM_SECURITY 0x03
 #endif
@@ -578,32 +494,6 @@ static inline pid_t gettid(void) {
 #define MAX_HANDLE_SZ 128
 #endif
 
-#ifndef __NR_name_to_handle_at
-#  if defined(__x86_64__)
-#    define __NR_name_to_handle_at 303
-#  elif defined(__i386__)
-#    define __NR_name_to_handle_at 341
-#  elif defined(__arm__)
-#    define __NR_name_to_handle_at 370
-#  elif defined(__powerpc__)
-#    define __NR_name_to_handle_at 345
-#  else
-#    error "__NR_name_to_handle_at is not defined"
-#  endif
-#endif
-
-#if !HAVE_DECL_NAME_TO_HANDLE_AT
-struct file_handle {
-        unsigned int handle_bytes;
-        int handle_type;
-        unsigned char f_handle[0];
-};
-
-static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
-        return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
-}
-#endif
-
 #ifndef HAVE_SECURE_GETENV
 #  ifdef HAVE___SECURE_GETENV
 #    define secure_getenv __secure_getenv
@@ -652,22 +542,6 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
 
 #endif
 
-#ifndef __NR_setns
-#  if defined(__x86_64__)
-#    define __NR_setns 308
-#  elif defined(__i386__)
-#    define __NR_setns 346
-#  else
-#    error "__NR_setns is not defined"
-#  endif
-#endif
-
-#if !HAVE_DECL_SETNS
-static inline int setns(int fd, int nstype) {
-        return syscall(__NR_setns, fd, nstype);
-}
-#endif
-
 #if !HAVE_DECL_LO_FLAGS_PARTSCAN
 #define LO_FLAGS_PARTSCAN 8
 #endif
@@ -1072,72 +946,11 @@ static inline int setns(int fd, int nstype) {
 #define CAP_AUDIT_READ 37
 #endif
 
-static inline int raw_clone(unsigned long flags, void *child_stack) {
-#if defined(__s390__) || defined(__CRIS__)
-        /* On s390 and cris the order of the first and second arguments
-         * of the raw clone() system call is reversed. */
-        return (int) syscall(__NR_clone, child_stack, flags);
-#else
-        return (int) syscall(__NR_clone, flags, child_stack);
-#endif
-}
-
-static inline pid_t raw_getpid(void) {
-#if defined(__alpha__)
-        return (pid_t) syscall(__NR_getxpid);
-#else
-        return (pid_t) syscall(__NR_getpid);
-#endif
-}
-
 #if 0 /// UNNEEDED by elogind
-
-#if !HAVE_DECL_RENAMEAT2
-
-
-#ifndef __NR_renameat2
-#  if defined __x86_64__
-#    define __NR_renameat2 316
-#  elif defined __arm__
-#    define __NR_renameat2 382
-#  elif defined _MIPS_SIM
-#    if _MIPS_SIM == _MIPS_SIM_ABI32
-#      define __NR_renameat2 4351
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_NABI32
-#      define __NR_renameat2 6315
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_ABI64
-#      define __NR_renameat2 5311
-#    endif
-#  elif defined __i386__
-#    define __NR_renameat2 353
-#  else
-#    warning "__NR_renameat2 unknown for your architecture"
-#    define __NR_renameat2 0xffffffff
-#  endif
-#endif
-
-static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
-        return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
-}
-#endif
-
 #ifndef RENAME_NOREPLACE
 #define RENAME_NOREPLACE (1 << 0)
 #endif
 
-#if !HAVE_DECL_KCMP
-static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
-#if defined(__NR_kcmp)
-        return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
-#else
-        errno = ENOSYS;
-        return -1;
-#endif
-}
-#endif
-
 #ifndef KCMP_FILE
 #define KCMP_FILE 0
 #endif
@@ -1154,35 +967,6 @@ static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, uns
 typedef int32_t key_serial_t;
 #endif
 
-#if !HAVE_DECL_KEYCTL
-static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
-#if defined(__NR_keyctl)
-        return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
-#else
-        errno = ENOSYS;
-        return -1;
-#endif
-}
-
-static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
-#if defined (__NR_add_key)
-        return syscall(__NR_add_key, type, description, payload, plen, ringid);
-#else
-        errno = ENOSYS;
-        return -1;
-#endif
-}
-
-static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
-#if defined (__NR_request_key)
-        return syscall(__NR_request_key, type, description, callout_info, destringid);
-#else
-        errno = ENOSYS;
-        return -1;
-#endif
-}
-#endif
-
 #ifndef KEYCTL_READ
 #define KEYCTL_READ 11
 #endif
@@ -1236,32 +1020,4 @@ static inline key_serial_t request_key(const char *type, const char *description
 
 #endif
 
-#ifndef __NR_copy_file_range
-#  if defined(__x86_64__)
-#    define __NR_copy_file_range 326
-#  elif defined(__i386__)
-#    define __NR_copy_file_range 377
-#  elif defined __s390__
-#    define __NR_copy_file_range 375
-#  elif defined __arm__
-#    define __NR_copy_file_range 391
-#  elif defined __aarch64__
-#    define __NR_copy_file_range 285
-#  else
-#    warning "__NR_copy_file_range not defined for your architecture"
-#  endif
-#endif
-
-#if !HAVE_DECL_COPY_FILE_RANGE
-static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
-                                      int fd_out, loff_t *off_out,
-                                      size_t len,
-                                      unsigned int flags) {
-#ifdef __NR_copy_file_range
-        return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags);
-#else
-        errno = ENOSYS;
-        return -1;
-#endif
-}
-#endif
+#include "missing_syscall.h"
index 42c39ee..abfe62a 100644 (file)
@@ -1,32 +1,34 @@
 #pragma once
 
 /***
-  This file is part of elogind.
+  This file is part of systemd.
 
   Copyright 2010 Lennart Poettering
   Copyright 2016 Zbigniew Jędrzejewski-Szmek
 
-  elogind is free software; you can redistribute it and/or modify it
+  systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2.1 of the License, or
   (at your option) any later version.
 
-  elogind is distributed in the hope that it will be useful, but
+  systemd is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
 /* Missing glibc definitions to access certain kernel APIs */
 
+#if 0 /// UNNEEDED by elogind
 #if !HAVE_DECL_PIVOT_ROOT
 static inline int pivot_root(const char *new_root, const char *put_old) {
         return syscall(SYS_pivot_root, new_root, put_old);
 }
 #endif
+#endif // 0
 
 /* ======================================================================= */
 
@@ -178,6 +180,7 @@ static inline int setns(int fd, int nstype) {
 
 /* ======================================================================= */
 
+#if 0 /// UNNEEDED by elogind
 static inline int raw_clone(unsigned long flags, void *child_stack) {
 #if defined(__s390__) || defined(__CRIS__)
         /* On s390 and cris the order of the first and second arguments
@@ -276,6 +279,7 @@ static inline key_serial_t request_key(const char *type, const char *description
 #  endif
 }
 #endif
+#endif // 0
 
 /* ======================================================================= */
 
index 6373263..d0208e9 100644 (file)
@@ -23,7 +23,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-//#include <xlocale.h>
+#if defined(__GLIBC__)
+#  include <xlocale.h>
+#endif // defined(__GLIBC__)
 
 #include "alloc-util.h"
 //#include "extract-word.h"
index ea70c5e..250f887 100644 (file)
@@ -35,7 +35,6 @@ int parse_mode(const char *s, mode_t *ret);
 int parse_ifindex(const char *s, int *ret);
 
 int parse_size(const char *t, uint64_t base, uint64_t *size);
-
 #if 0 /// UNNEEDED by elogind
 int parse_range(const char *t, unsigned *lower, unsigned *upper);
 
index 5f4252f..123b4ce 100644 (file)
@@ -100,9 +100,9 @@ int path_make_absolute_cwd(const char *p, char **ret) {
         else {
                 _cleanup_free_ char *cwd = NULL;
 
-        cwd = get_current_dir_name();
-        if (!cwd)
-                        return -errno;
+                cwd = get_current_dir_name();
+                if (!cwd)
+                        return negative_errno();
 
                 c = strjoin(cwd, "/", p, NULL);
         }
@@ -477,10 +477,10 @@ int find_binary(const char *name, char **ret) {
                 return 0;
         }
 
-                /**
-                 * Plain getenv, not secure_getenv, because we want
-                 * to actually allow the user to pick the binary.
-                 */
+        /**
+         * Plain getenv, not secure_getenv, because we want
+         * to actually allow the user to pick the binary.
+         */
         p = getenv("PATH");
         if (!p)
                 p = DEFAULT_PATH;
@@ -497,7 +497,7 @@ int find_binary(const char *name, char **ret) {
                         break;
 
                 if (!path_is_absolute(element))
-                                continue;
+                        continue;
 
                 j = strjoin(element, "/", name, NULL);
                 if (!j)
@@ -762,37 +762,53 @@ char *file_in_same_dir(const char *path, const char *filename) {
         return ret;
 }
 
-bool hidden_file_allow_backup(const char *filename) {
-        assert(filename);
-
-        return
-                filename[0] == '.' ||
-                streq(filename, "lost+found") ||
-                streq(filename, "aquota.user") ||
-                streq(filename, "aquota.group") ||
-                endswith(filename, ".rpmnew") ||
-                endswith(filename, ".rpmsave") ||
-                endswith(filename, ".rpmorig") ||
-                endswith(filename, ".dpkg-old") ||
-                endswith(filename, ".dpkg-new") ||
-                endswith(filename, ".dpkg-tmp") ||
-                endswith(filename, ".dpkg-dist") ||
-                endswith(filename, ".dpkg-bak") ||
-                endswith(filename, ".dpkg-backup") ||
-                endswith(filename, ".dpkg-remove") ||
-                endswith(filename, ".ucf-new") ||
-                endswith(filename, ".ucf-old") ||
-                endswith(filename, ".ucf-dist") ||
-                endswith(filename, ".swp");
-}
+bool hidden_or_backup_file(const char *filename) {
+        const char *p;
 
-bool hidden_file(const char *filename) {
         assert(filename);
 
-        if (endswith(filename, "~"))
+        if (filename[0] == '.' ||
+            streq(filename, "lost+found") ||
+            streq(filename, "aquota.user") ||
+            streq(filename, "aquota.group") ||
+            endswith(filename, "~"))
                 return true;
 
-        return hidden_file_allow_backup(filename);
+        p = strrchr(filename, '.');
+        if (!p)
+                return false;
+
+        /* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up
+         * with always new suffixes and that everybody else should just adjust to that, then it really should be on
+         * them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt
+         * one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional
+         * string. Specifically: there's now:
+         *
+         *    The generic suffixes "~" and ".bak" for backup files
+         *    The generic prefix "." for hidden files
+         *
+         * Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist"
+         * or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead.
+         */
+
+        return STR_IN_SET(p + 1,
+                          "rpmnew",
+                          "rpmsave",
+                          "rpmorig",
+                          "dpkg-old",
+                          "dpkg-new",
+                          "dpkg-tmp",
+                          "dpkg-dist",
+                          "dpkg-bak",
+                          "dpkg-backup",
+                          "dpkg-remove",
+                          "ucf-new",
+                          "ucf-old",
+                          "ucf-dist",
+                          "swp",
+                          "bak",
+                          "old",
+                          "new");
 }
 
 #if 0 /// UNNEEDED by elogind
index 99035aa..540a69c 100644 (file)
@@ -55,6 +55,25 @@ bool path_equal_or_files_same(const char *a, const char *b);
 #if 0 /// UNNEEDED by elogind
 char* path_join(const char *root, const char *path, const char *rest);
 
+static inline bool path_equal_ptr(const char *a, const char *b) {
+        return !!a == !!b && (!a || path_equal(a, b));
+}
+#endif // 0
+
+/* Note: the search terminates on the first NULL item. */
+#define PATH_IN_SET(p, ...)                                     \
+        ({                                                      \
+                char **s;                                       \
+                bool _found = false;                            \
+                STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__))         \
+                        if (path_equal(p, *s)) {                \
+                               _found = true;                   \
+                               break;                           \
+                        }                                       \
+                _found;                                         \
+        })
+
+#if 0 /// UNNEEDED by elogind
 int path_strv_make_absolute_cwd(char **l);
 #endif // 0
 char** path_strv_resolve(char **l, const char *prefix);
@@ -117,8 +136,7 @@ bool path_is_safe(const char *p) _pure_;
 
 char *file_in_same_dir(const char *path, const char *filename);
 
-bool hidden_file_allow_backup(const char *filename);
-bool hidden_file(const char *filename) _pure_;
+bool hidden_or_backup_file(const char *filename) _pure_;
 
 #if 0 /// UNNEEDED by elogind
 bool is_device_path(const char *path);
index d146638..f418b85 100644 (file)
@@ -38,7 +38,7 @@
 #endif
 
 #include "alloc-util.h"
-#include "architecture.h"
+//#include "architecture.h"
 #include "escape.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -207,7 +207,7 @@ void rename_process(const char name[8]) {
          * "systemd"). If you pass a longer string it will be
          * truncated */
 
-        prctl(PR_SET_NAME, name);
+        (void) prctl(PR_SET_NAME, name);
 
         if (program_invocation_name)
                 strncpy(program_invocation_name, name, strlen(program_invocation_name));
@@ -413,7 +413,7 @@ int get_process_environ(pid_t pid, char **env) {
                 if (!outcome)
                         return -ENOMEM;
         } else
-        outcome[sz] = '\0';
+                outcome[sz] = '\0';
 
         *env = outcome;
         outcome = NULL;
@@ -534,17 +534,23 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_cod
         return -EPROTO;
 }
 
-void sigkill_wait(pid_t *pid) {
+#if 0 /// UNNEEDED by elogind
+void sigkill_wait(pid_t pid) {
+        assert(pid > 1);
+
+        if (kill(pid, SIGKILL) > 0)
+                (void) wait_for_terminate(pid, NULL);
+}
+
+void sigkill_waitp(pid_t *pid) {
         if (!pid)
                 return;
         if (*pid <= 1)
                 return;
 
-        if (kill(*pid, SIGKILL) > 0)
-                (void) wait_for_terminate(*pid, NULL);
+        sigkill_wait(*pid);
 }
 
-#if 0 /// UNNEEDED by elogind
 int kill_and_sigcont(pid_t pid, int sig) {
         int r;
 
@@ -672,6 +678,8 @@ bool is_main_thread(void) {
 #if 0 /// UNNEEDED by elogind
 noreturn void freeze(void) {
 
+        log_close();
+
         /* Make sure nobody waits for us on a socket anymore */
         close_all_fds(NULL, 0);
 
index 66b6cd1..6cf3a40 100644 (file)
@@ -47,7 +47,6 @@ int get_process_state(pid_t pid);
 int get_process_comm(pid_t pid, char **name);
 int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
 int get_process_exe(pid_t pid, char **name);
-
 #if 0 /// UNNEEDED by elogind
 int get_process_uid(pid_t pid, uid_t *uid);
 int get_process_gid(pid_t pid, gid_t *gid);
@@ -61,15 +60,14 @@ int get_process_ppid(pid_t pid, pid_t *ppid);
 int wait_for_terminate(pid_t pid, siginfo_t *status);
 int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
 
-void sigkill_wait(pid_t *pid);
-#define _cleanup_sigkill_wait_ _cleanup_(sigkill_wait)
-
 #if 0 /// UNNEEDED by elogind
+void sigkill_wait(pid_t pid);
+void sigkill_waitp(pid_t *pid);
+
 int kill_and_sigcont(pid_t pid, int sig);
 
 void rename_process(const char name[8]);
 #endif // 0
-
 int is_kernel_thread(pid_t pid);
 
 int getenv_for_pid(pid_t pid, const char *field, char **_value);
index 6912b23..474bfbf 100644 (file)
@@ -128,7 +128,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
                                 continue;
                         }
 
-#if 0
+#if 0 /// elogind does not support BTRFS this directly
                         if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) {
 
                                 /* This could be a subvolume, try to remove it */
@@ -190,7 +190,7 @@ int rm_rf(const char *path, RemoveFlags flags) {
                 return -EPERM;
         }
 
-#if 0
+#if 0 /// elogind does not support BTRFS this directly
         if ((flags & (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) == (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) {
                 /* Try to remove as subvolume first */
                 r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
index 700b2e8..835d3fd 100644 (file)
@@ -82,31 +82,23 @@ void mac_selinux_retest(void) {
 }
 #endif // 0
 
-int mac_selinux_init(const char *prefix) {
+int mac_selinux_init(void) {
         int r = 0;
 
 #ifdef HAVE_SELINUX
         usec_t before_timestamp, after_timestamp;
         struct mallinfo before_mallinfo, after_mallinfo;
 
-        if (!mac_selinux_use())
+        if (label_hnd)
                 return 0;
 
-        if (label_hnd)
+        if (!mac_selinux_use())
                 return 0;
 
         before_mallinfo = mallinfo();
         before_timestamp = now(CLOCK_MONOTONIC);
 
-        if (prefix) {
-                struct selinux_opt options[] = {
-                        { .type = SELABEL_OPT_SUBSET, .value = prefix },
-                };
-
-                label_hnd = selabel_open(SELABEL_CTX_FILE, options, ELEMENTSOF(options));
-        } else
-                label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
-
+        label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
         if (!label_hnd) {
                 log_enforcing("Failed to initialize SELinux context: %m");
                 r = security_getenforce() == 1 ? -errno : 0;
@@ -164,7 +156,7 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
                         return 0;
 
                 if (r >= 0) {
-                        r = lsetfilecon(path, fcon);
+                        r = lsetfilecon_raw(path, fcon);
 
                         /* If the FS doesn't support labels, then exit without warning */
                         if (r < 0 && errno == EOPNOTSUPP)
@@ -230,7 +222,7 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
                 return -errno;
 
         sclass = string_to_security_class("process");
-        r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+        r = security_compute_create_raw(mycon, fcon, sclass, (security_context_t *) label);
         if (r < 0)
                 return -errno;
 #endif
@@ -275,7 +267,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
         if (r < 0)
                 return -errno;
 
-        r = getpeercon(socket_fd, &peercon);
+        r = getpeercon_raw(socket_fd, &peercon);
         if (r < 0)
                 return -errno;
 
@@ -309,7 +301,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
                 return -ENOMEM;
 
         sclass = string_to_security_class("process");
-        r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+        r = security_compute_create_raw(mycon, fcon, sclass, (security_context_t *) label);
         if (r < 0)
                 return -errno;
 #endif
@@ -358,16 +350,16 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
         }
 
         if (r < 0) {
-        /* No context specified by the policy? Proceed without setting it. */
+                /* No context specified by the policy? Proceed without setting it. */
                 if (errno == ENOENT)
-                return 0;
+                        return 0;
 
                 log_enforcing("Failed to determine SELinux security context for %s: %m", path);
         } else {
-                if (setfscreatecon(filecon) >= 0)
+                if (setfscreatecon_raw(filecon) >= 0)
                         return 0; /* Success! */
 
-                        log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
+                log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
         }
 
         if (security_getenforce() > 0)
@@ -385,7 +377,7 @@ void mac_selinux_create_file_clear(void) {
         if (!mac_selinux_use())
                 return;
 
-        setfscreatecon(NULL);
+        setfscreatecon_raw(NULL);
 #endif
 }
 
@@ -417,7 +409,7 @@ void mac_selinux_create_socket_clear(void) {
         if (!mac_selinux_use())
                 return;
 
-        setsockcreatecon(NULL);
+        setsockcreatecon_raw(NULL);
 #endif
 }
 
@@ -476,7 +468,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
                         return -errno;
 
         } else {
-                if (setfscreatecon(fcon) < 0) {
+                if (setfscreatecon_raw(fcon) < 0) {
                         log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path);
                         if (security_getenforce() > 0)
                                 return -errno;
@@ -487,7 +479,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
         r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
 
         if (context_changed)
-        setfscreatecon(NULL);
+                setfscreatecon_raw(NULL);
 
         return r;
 
index e2d21a4..0528b77 100644 (file)
@@ -31,7 +31,7 @@ bool mac_selinux_have(void);
 void mac_selinux_retest(void);
 #endif // 0
 
-int mac_selinux_init(const char *prefix);
+int mac_selinux_init(void);
 #if 0 /// UNNEEDED by elogind
 void mac_selinux_finish(void);
 #endif // 0
index 8edaae5..060e8ba 100644 (file)
@@ -56,7 +56,7 @@ void siphash24_init(struct siphash *state, const uint8_t k[16]) {
         k1 = unaligned_read_le64(k + 8);
 
         *state = (struct siphash) {
-  /* "somepseudorandomlygeneratedbytes" */
+                /* "somepseudorandomlygeneratedbytes" */
                 .v0 = 0x736f6d6570736575ULL ^ k0,
                 .v1 = 0x646f72616e646f6dULL ^ k1,
                 .v2 = 0x6c7967656e657261ULL ^ k0,
@@ -77,16 +77,16 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
         assert(state);
 
         /* Update total length */
-  state->inlen += inlen;
+        state->inlen += inlen;
 
         /* If padding exists, fill it out */
-  if (left > 0) {
-    for ( ; in < end && left < 8; in ++, left ++ )
-                        state->padding |= ( ( uint64_t )*in ) << (left * 8);
+        if (left > 0) {
+                for ( ; in < end && left < 8; in ++, left ++)
+                        state->padding |= ((uint64_t) *in) << (left * 8);
 
-    if (in == end && left < 8)
+                if (in == end && left < 8)
                         /* We did not have enough input to fill out the padding completely */
-      return;
+                        return;
 
 #ifdef DEBUG
                 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
@@ -96,17 +96,17 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
                 printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
 #endif
 
-    state->v3 ^= state->padding;
+                state->v3 ^= state->padding;
                 sipround(state);
                 sipround(state);
-    state->v0 ^= state->padding;
+                state->v0 ^= state->padding;
 
-    state->padding = 0;
-  }
+                state->padding = 0;
+        }
 
-        end -= ( state->inlen % sizeof (uint64_t) );
+        end -= (state->inlen % sizeof(uint64_t));
 
-        for ( ; in < end; in += 8 ) {
+        for ( ; in < end; in += 8) {
                 m = unaligned_read_le64(in);
 #ifdef DEBUG
                 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
@@ -115,13 +115,13 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
                 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
                 printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m);
 #endif
-    state->v3 ^= m;
+                state->v3 ^= m;
                 sipround(state);
                 sipround(state);
-    state->v0 ^= m;
-  }
+                state->v0 ^= m;
+        }
 
-  left = state->inlen & 7;
+        left = state->inlen & 7;
         switch (left) {
                 case 7:
                         state->padding |= ((uint64_t) in[6]) << 48;
@@ -139,7 +139,7 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
                         state->padding |= ((uint64_t) in[0]);
                 case 0:
                         break;
-  }
+        }
 }
 
 uint64_t siphash24_finalize(struct siphash *state) {
@@ -147,20 +147,20 @@ uint64_t siphash24_finalize(struct siphash *state) {
 
         assert(state);
 
-        b = state->padding | (( ( uint64_t )state->inlen ) << 56);
+        b = state->padding | (((uint64_t) state->inlen) << 56);
 
 #ifdef DEBUG
-        printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t)state->v0);
-        printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t)state->v1);
-        printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t)state->v2);
-        printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t)state->v3);
+        printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
+        printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
+        printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
+        printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
         printf("(%3zu) padding   %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
 #endif
 
-  state->v3 ^= b;
+        state->v3 ^= b;
         sipround(state);
         sipround(state);
-  state->v0 ^= b;
+        state->v0 ^= b;
 
 #ifdef DEBUG
         printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
@@ -168,7 +168,7 @@ uint64_t siphash24_finalize(struct siphash *state) {
         printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
         printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
 #endif
-  state->v2 ^= 0xff;
+        state->v2 ^= 0xff;
 
         sipround(state);
         sipround(state);
@@ -179,7 +179,7 @@ uint64_t siphash24_finalize(struct siphash *state) {
 }
 
 uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) {
-  struct siphash state;
+        struct siphash state;
 
         assert(in);
         assert(k);
index 73e1931..5efd09f 100644 (file)
@@ -42,6 +42,7 @@
 #include "socket-util.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "strv.h"
 #include "user-util.h"
 #include "util.h"
 
@@ -800,6 +801,42 @@ static const char* const ip_tos_table[] = {
 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
 #endif // 0
 
+bool ifname_valid(const char *p) {
+        bool numeric = true;
+
+        /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
+         * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
+         * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
+
+        if (isempty(p))
+                return false;
+
+        if (strlen(p) >= IFNAMSIZ)
+                return false;
+
+        if (STR_IN_SET(p, ".", ".."))
+                return false;
+
+        while (*p) {
+                if ((unsigned char) *p >= 127U)
+                        return false;
+
+                if ((unsigned char) *p <= 32U)
+                        return false;
+
+                if (*p == ':' || *p == '/')
+                        return false;
+
+                numeric = numeric && (*p >= '0' && *p <= '9');
+                p++;
+        }
+
+        if (numeric)
+                return false;
+
+        return true;
+}
+
 int getpeercred(int fd, struct ucred *ucred) {
         socklen_t n = sizeof(struct ucred);
         struct ucred u;
@@ -943,4 +980,77 @@ int receive_one_fd(int transport_fd, int flags) {
 
         return *(int*) CMSG_DATA(found);
 }
+
+ssize_t next_datagram_size_fd(int fd) {
+        ssize_t l;
+        int k;
+
+        /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
+         * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
+         * do. This difference is actually of major importance as we need to be sure that the size returned here
+         * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
+         * the wrong size. */
+
+        l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
+        if (l < 0) {
+                if (errno == EOPNOTSUPP)
+                        goto fallback;
+
+                return -errno;
+        }
+        if (l == 0)
+                goto fallback;
+
+        return l;
+
+fallback:
+        k = 0;
+
+        /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
+         * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
+
+        if (ioctl(fd, FIONREAD, &k) < 0)
+                return -errno;
+
+        return (ssize_t) k;
+}
+
+int flush_accept(int fd) {
+
+        struct pollfd pollfd = {
+                .fd = fd,
+                .events = POLLIN,
+        };
+        int r;
+
+
+        /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
+
+        for (;;) {
+                int cfd;
+
+                r = poll(&pollfd, 1, 0);
+                if (r < 0) {
+                        if (errno == EINTR)
+                                continue;
+
+                        return -errno;
+
+                } else if (r == 0)
+                        return 0;
+
+                cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+                if (cfd < 0) {
+                        if (errno == EINTR)
+                                continue;
+
+                        if (errno == EAGAIN)
+                                return 0;
+
+                        return -errno;
+                }
+
+                close(cfd);
+        }
+}
 #endif // 0
index 8850d9f..b5d1dc3 100644 (file)
@@ -129,6 +129,8 @@ int ip_tos_to_string_alloc(int i, char **s);
 int ip_tos_from_string(const char *s);
 #endif // 0
 
+bool ifname_valid(const char *p);
+
 int getpeercred(int fd, struct ucred *ucred);
 int getpeersec(int fd, char **ret);
 
@@ -139,6 +141,10 @@ int send_one_fd_sa(int transport_fd,
 #define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags)
 #if 0 /// UNNEEDED by elogind
 int receive_one_fd(int transport_fd, int flags);
+
+ssize_t next_datagram_size_fd(int fd);
+
+int flush_accept(int fd);
 #endif // 0
 
 #define CMSG_FOREACH(cmsg, mh)                                          \
index 757c105..bd1144b 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#if defined(__GLIBC__) && defined(HAVE_PRINTF_H)
 #include <printf.h>
-#else
-#include "parse-printf-format.h"
-#endif
 #include <stdarg.h>
 #include <stdio.h>
 #include <sys/types.h>
index 7757a44..93bb130 100644 (file)
@@ -319,7 +319,7 @@ char **strv_split_newlines(const char *s) {
                 return l;
 
         if (isempty(l[n - 1]))
-                l[n-1] = mfree(l[n-1]);
+                l[n - 1] = mfree(l[n - 1]);
 
         return l;
 }
index 8e83ffd..591a452 100644 (file)
@@ -54,6 +54,7 @@ int strv_extend(char ***l, const char *value);
 #if 0 /// UNNEEDED by elogind
 int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
 #endif // 0
+int strv_extend_front(char ***l, const char *value);
 int strv_push(char ***l, char *value);
 int strv_push_pair(char ***l, char *a, char *b);
 int strv_push_prepend(char ***l, char *value);
@@ -90,6 +91,7 @@ char **strv_split_newlines(const char *s);
 
 int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
 #endif // 0
+
 char *strv_join(char **l, const char *separator);
 #if 0 /// UNNEEDED by elogind
 char *strv_join_quoted(char **l);
@@ -102,6 +104,7 @@ int strv_make_nulstr(char **l, char **p, size_t *n);
 
 bool strv_overlap(char **a, char **b) _pure_;
 #endif // 0
+
 #define STRV_FOREACH(s, l)                      \
         for ((s) = (l); (s) && *(s); (s)++)
 
index 75a0d6f..cb1e6a0 100644 (file)
@@ -1149,14 +1149,19 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
 #endif // 0
 
 bool colors_enabled(void) {
-        const char *colors;
+        static int enabled = -1;
 
-        colors = getenv("SYSTEMD_COLORS");
-        if (!colors) {
-                if (streq_ptr(getenv("TERM"), "dumb"))
-                        return false;
-                return on_tty();
+        if (_unlikely_(enabled < 0)) {
+                const char *colors;
+
+                colors = getenv("SYSTEMD_COLORS");
+                if (colors)
+                        enabled = parse_boolean(colors) != 0;
+                else if (streq_ptr(getenv("TERM"), "dumb"))
+                        enabled = false;
+                else
+                        enabled = on_tty();
         }
 
-        return parse_boolean(colors) != 0;
+        return enabled;
 }
index 2a3957d..97db1e2 100644 (file)
 static nsec_t timespec_load_nsec(const struct timespec *ts);
 #endif // 0
 
+static clockid_t map_clock_id(clockid_t c) {
+
+        /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will
+         * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is
+         * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on
+         * those archs. */
+
+        switch (c) {
+
+        case CLOCK_BOOTTIME_ALARM:
+                return CLOCK_BOOTTIME;
+
+        case CLOCK_REALTIME_ALARM:
+                return CLOCK_REALTIME;
+
+        default:
+                return c;
+        }
+}
+
 usec_t now(clockid_t clock_id) {
         struct timespec ts;
 
-        assert_se(clock_gettime(clock_id, &ts) == 0);
+        assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0);
 
         return timespec_load(&ts);
 }
@@ -56,7 +76,7 @@ usec_t now(clockid_t clock_id) {
 nsec_t now_nsec(clockid_t clock_id) {
         struct timespec ts;
 
-        assert_se(clock_gettime(clock_id, &ts) == 0);
+        assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0);
 
         return timespec_load_nsec(&ts);
 }
@@ -125,8 +145,7 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
 usec_t timespec_load(const struct timespec *ts) {
         assert(ts);
 
-        if (ts->tv_sec == (time_t) -1 &&
-            ts->tv_nsec == (long) -1)
+        if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1)
                 return USEC_INFINITY;
 
         if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
@@ -141,13 +160,13 @@ usec_t timespec_load(const struct timespec *ts) {
 static nsec_t timespec_load_nsec(const struct timespec *ts) {
         assert(ts);
 
-        if (ts->tv_sec == (time_t) -1 &&
-            ts->tv_nsec == (long) -1)
+        if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1)
                 return NSEC_INFINITY;
 
-        return
-                (nsec_t) ts->tv_sec * NSEC_PER_SEC +
-                (nsec_t) ts->tv_nsec;
+        if ((nsec_t) ts->tv_sec >= (UINT64_MAX - ts->tv_nsec) / NSEC_PER_SEC)
+                return NSEC_INFINITY;
+
+        return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec;
 }
 #endif // 0
 
@@ -314,15 +333,15 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
                 const char *suffix;
                 usec_t usec;
         } table[] = {
-                { "y", USEC_PER_YEAR },
-                { "month", USEC_PER_MONTH },
-                { "w", USEC_PER_WEEK },
-                { "d", USEC_PER_DAY },
-                { "h", USEC_PER_HOUR },
-                { "min", USEC_PER_MINUTE },
-                { "s", USEC_PER_SEC },
-                { "ms", USEC_PER_MSEC },
-                { "us", 1 },
+                { "y",     USEC_PER_YEAR   },
+                { "month", USEC_PER_MONTH  },
+                { "w",     USEC_PER_WEEK   },
+                { "d",     USEC_PER_DAY    },
+                { "h",     USEC_PER_HOUR   },
+                { "min",   USEC_PER_MINUTE },
+                { "s",     USEC_PER_SEC    },
+                { "ms",    USEC_PER_MSEC   },
+                { "us",    1               },
         };
 
         unsigned i;
@@ -452,6 +471,7 @@ int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
         return 0;
 }
 
+#endif // 0
 int timestamp_deserialize(const char *value, usec_t *timestamp) {
         int r;
 
@@ -464,6 +484,7 @@ int timestamp_deserialize(const char *value, usec_t *timestamp) {
         return r;
 }
 
+#if 0 /// UNNEEDED by elogind
 int parse_timestamp(const char *t, usec_t *usec) {
         static const struct {
                 const char *name;
@@ -699,42 +720,56 @@ finish:
 }
 #endif // 0
 
-int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
-
+static char* extract_multiplier(char *p, usec_t *multiplier) {
         static const struct {
                 const char *suffix;
                 usec_t usec;
         } table[] = {
-                { "seconds", USEC_PER_SEC },
-                { "second", USEC_PER_SEC },
-                { "sec", USEC_PER_SEC },
-                { "s", USEC_PER_SEC },
+                { "seconds", USEC_PER_SEC    },
+                { "second",  USEC_PER_SEC    },
+                { "sec",     USEC_PER_SEC    },
+                { "s",       USEC_PER_SEC    },
                 { "minutes", USEC_PER_MINUTE },
-                { "minute", USEC_PER_MINUTE },
-                { "min", USEC_PER_MINUTE },
-                { "months", USEC_PER_MONTH },
-                { "month", USEC_PER_MONTH },
+                { "minute",  USEC_PER_MINUTE },
+                { "min",     USEC_PER_MINUTE },
+                { "months",  USEC_PER_MONTH  },
+                { "month",   USEC_PER_MONTH  },
                 { "M",       USEC_PER_MONTH  },
-                { "msec", USEC_PER_MSEC },
-                { "ms", USEC_PER_MSEC },
-                { "m", USEC_PER_MINUTE },
-                { "hours", USEC_PER_HOUR },
-                { "hour", USEC_PER_HOUR },
-                { "hr", USEC_PER_HOUR },
-                { "h", USEC_PER_HOUR },
-                { "days", USEC_PER_DAY },
-                { "day", USEC_PER_DAY },
-                { "d", USEC_PER_DAY },
-                { "weeks", USEC_PER_WEEK },
-                { "week", USEC_PER_WEEK },
-                { "w", USEC_PER_WEEK },
-                { "years", USEC_PER_YEAR },
-                { "year", USEC_PER_YEAR },
-                { "y", USEC_PER_YEAR },
-                { "usec", 1ULL },
-                { "us", 1ULL },
+                { "msec",    USEC_PER_MSEC   },
+                { "ms",      USEC_PER_MSEC   },
+                { "m",       USEC_PER_MINUTE },
+                { "hours",   USEC_PER_HOUR   },
+                { "hour",    USEC_PER_HOUR   },
+                { "hr",      USEC_PER_HOUR   },
+                { "h",       USEC_PER_HOUR   },
+                { "days",    USEC_PER_DAY    },
+                { "day",     USEC_PER_DAY    },
+                { "d",       USEC_PER_DAY    },
+                { "weeks",   USEC_PER_WEEK   },
+                { "week",    USEC_PER_WEEK   },
+                { "w",       USEC_PER_WEEK   },
+                { "years",   USEC_PER_YEAR   },
+                { "year",    USEC_PER_YEAR   },
+                { "y",       USEC_PER_YEAR   },
+                { "usec",    1ULL            },
+                { "us",      1ULL            },
         };
+        unsigned i;
+
+        for (i = 0; i < ELEMENTSOF(table); i++) {
+                char *e;
 
+                e = startswith(p, table[i].suffix);
+                if (e) {
+                        *multiplier = table[i].usec;
+                        return e;
+                }
+        }
+
+        return p;
+}
+
+int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
         const char *p, *s;
         usec_t r = 0;
         bool something = false;
@@ -759,8 +794,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
         for (;;) {
                 long long l, z = 0;
                 char *e;
-                unsigned i, n = 0;
-                usec_t multiplier, k;
+                unsigned n = 0;
+                usec_t multiplier = default_unit, k;
 
                 p += strspn(p, WHITESPACE);
 
@@ -773,10 +808,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
 
                 errno = 0;
                 l = strtoll(p, &e, 10);
-
                 if (errno > 0)
                         return -errno;
-
                 if (l < 0)
                         return -ERANGE;
 
@@ -800,18 +833,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
                         return -EINVAL;
 
                 e += strspn(e, WHITESPACE);
-
-                for (i = 0; i < ELEMENTSOF(table); i++)
-                        if (startswith(e, table[i].suffix)) {
-                                multiplier = table[i].usec;
-                                p = e + strlen(table[i].suffix);
-                                break;
-                        }
-
-                if (i >= ELEMENTSOF(table)) {
-                        multiplier = default_unit;
-                        p = e;
-                }
+                p = extract_multiplier(e, &multiplier);
 
                 something = true;
 
@@ -1075,6 +1097,7 @@ bool timezone_is_valid(const char *name) {
         return true;
 }
 
+#endif // 0
 bool clock_boottime_supported(void) {
         static int supported = -1;
 
@@ -1095,6 +1118,7 @@ bool clock_boottime_supported(void) {
         return supported;
 }
 
+#if 0 /// UNNEEDED by elogind
 clockid_t clock_boottime_or_monotonic(void) {
         if (clock_boottime_supported())
                 return CLOCK_BOOTTIME;
index 3c3fcca..6feb75c 100644 (file)
@@ -108,7 +108,10 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
 #if 0 /// UNNEEDED by elogind
 void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
 int dual_timestamp_deserialize(const char *value, dual_timestamp *t);
+#endif // 0
+int timestamp_deserialize(const char *value, usec_t *timestamp);
 
+#if 0 /// UNNEEDED by elogind
 int parse_timestamp(const char *t, usec_t *usec);
 #endif // 0
 
@@ -122,6 +125,9 @@ bool ntp_synced(void);
 int get_timezones(char ***l);
 bool timezone_is_valid(const char *name);
 
+#endif // 0
+bool clock_boottime_supported(void);
+#if 0 /// UNNEEDED by elogind
 clockid_t clock_boottime_or_monotonic(void);
 #endif // 0
 
index 6e6bd3b..463301e 100644 (file)
@@ -761,7 +761,7 @@ int slice_build_parent_slice(const char *slice, char **ret) {
         else {
                 r = free_and_strdup(&s, "-.slice");
                 if (r < 0) {
-                free(s);
+                        free(s);
                         return r;
                 }
         }
index 68097b4..1ef6f5f 100644 (file)
@@ -785,16 +785,25 @@ uint64_t physical_memory(void) {
 }
 
 #if 0 /// UNNEEDED by elogind
-int update_reboot_param_file(const char *param) {
-        int r = 0;
+int update_reboot_parameter_and_warn(const char *param) {
+        int r;
+
+        if (isempty(param)) {
+                if (unlink("/run/systemd/reboot-param") < 0) {
+                        if (errno == ENOENT)
+                                return 0;
+
+                        return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m");
+                }
 
-        if (param) {
-                RUN_WITH_UMASK(0022)
-                        r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
+                return 0;
+        }
+
+        RUN_WITH_UMASK(0022) {
+                r = write_string_file("/run/systemd/reboot-param", param, WRITE_STRING_FILE_CREATE);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
-        } else
-                (void) unlink(REBOOT_PARAM_FILE);
+                        return log_warning_errno(r, "Failed to write reboot parameter file: %m");
+        }
 
         return 0;
 }
index 1fe660b..af5a4fc 100644 (file)
@@ -111,6 +111,16 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_
         qsort(base, nmemb, size, compar);
 }
 
+/**
+ * Normal memcpy requires src to be nonnull. We do nothing if n is 0.
+ */
+static inline void memcpy_safe(void *dst, const void *src, size_t n) {
+        if (n == 0)
+                return;
+        assert(src);
+        memcpy(dst, src, n);
+}
+
 #if 0 /// UNNEEDED by elogind
 int on_ac_power(void);
 #endif // 0
@@ -129,7 +139,6 @@ static inline void _reset_errno_(int *saved_errno) {
 
 #define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno
 
-#if 0 /// UNNEEDED by elogind
 static inline int negative_errno(void) {
         /* This helper should be used to shut up gcc if you know 'errno' is
          * negative. Instead of "return -errno;", use "return negative_errno();"
@@ -138,7 +147,6 @@ static inline int negative_errno(void) {
         assert_return(errno > 0, -EINVAL);
         return -errno;
 }
-#endif // 0
 
 static inline unsigned u64log2(uint64_t n) {
 #if __SIZEOF_LONG_LONG__ == 8
@@ -189,7 +197,7 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
 uint64_t physical_memory(void);
 
 #if 0 /// UNNEEDED by elogind
-int update_reboot_param_file(const char *param);
 #endif // 0
+int update_reboot_parameter_and_warn(const char *param);
 
 int version(void);
index 6eb1d0c..0c08201 100644 (file)
@@ -99,6 +99,8 @@ static int detect_vm_cpuid(void) {
                         : "0" (eax)
                 );
 
+                log_debug("Virtualization found, CPUID=%s", sig.text);
+
                 for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
                         if (streq(sig.text, cpuid_vendor_table[j].cpuid))
                                 return cpuid_vendor_table[j].id;
@@ -106,6 +108,7 @@ static int detect_vm_cpuid(void) {
                 return VIRTUALIZATION_VM_OTHER;
         }
 #endif
+        log_debug("No virtualization found in CPUID");
 
         return VIRTUALIZATION_NONE;
 }
@@ -122,19 +125,25 @@ static int detect_vm_device_tree(void) {
 
                 dir = opendir("/proc/device-tree");
                 if (!dir) {
-                        if (errno == ENOENT)
+                        if (errno == ENOENT) {
+                                log_debug_errno(errno, "/proc/device-tree: %m");
                                 return VIRTUALIZATION_NONE;
+                        }
                         return -errno;
                 }
 
                 FOREACH_DIRENT(dent, dir, return -errno)
-                        if (strstr(dent->d_name, "fw-cfg"))
+                        if (strstr(dent->d_name, "fw-cfg")) {
+                                log_debug("Virtualization QEMU: \"fw-cfg\" present in /proc/device-tree/%s", dent->d_name);
                                 return VIRTUALIZATION_QEMU;
+                        }
 
+                log_debug("No virtualization found in /proc/device-tree/*");
                 return VIRTUALIZATION_NONE;
         } else if (r < 0)
                 return r;
 
+        log_debug("Virtualization %s found in /proc/device-tree/hypervisor/compatible", hvtype);
         if (streq(hvtype, "linux,kvm"))
                 return VIRTUALIZATION_KVM;
         else if (strstr(hvtype, "xen"))
@@ -142,6 +151,7 @@ static int detect_vm_device_tree(void) {
         else
                 return VIRTUALIZATION_VM_OTHER;
 #else
+        log_debug("This platform does not support /proc/device-tree");
         return VIRTUALIZATION_NONE;
 #endif
 }
@@ -180,47 +190,77 @@ static int detect_vm_dmi(void) {
                 r = read_one_line_file(dmi_vendors[i], &s);
                 if (r < 0) {
                         if (r == -ENOENT)
-                        continue;
+                                continue;
 
                         return r;
-                        }
+                }
+
+
 
                 for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++)
-                        if (startswith(s, dmi_vendor_table[j].vendor))
+                        if (startswith(s, dmi_vendor_table[j].vendor)) {
+                                log_debug("Virtualization %s found in DMI (%s)", s, dmi_vendors[i]);
                                 return dmi_vendor_table[j].id;
+                        }
         }
 #endif
 
+        log_debug("No virtualization found in DMI");
+
         return VIRTUALIZATION_NONE;
 }
 
 static int detect_vm_xen(void) {
+        /* Check for Dom0 will be executed later in detect_vm_xen_dom0
+           Thats why we dont check the content of /proc/xen/capabilities here. */
+        if (access("/proc/xen/capabilities", F_OK) < 0) {
+                log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
+                return VIRTUALIZATION_NONE;
+        }
+
+        log_debug("Virtualization XEN found (/proc/xen/capabilities exists)");
+        return  VIRTUALIZATION_XEN;
+
+}
+
+static bool detect_vm_xen_dom0(void) {
         _cleanup_free_ char *domcap = NULL;
         char *cap, *i;
         int r;
 
         r = read_one_line_file("/proc/xen/capabilities", &domcap);
-        if (r == -ENOENT)
-                return VIRTUALIZATION_NONE;
+        if (r == -ENOENT) {
+                log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
+                return false;
+        }
+        if (r < 0)
+                return r;
 
         i = domcap;
-                while ((cap = strsep(&i, ",")))
-                        if (streq(cap, "control_d"))
-                                break;
+        while ((cap = strsep(&i, ",")))
+                if (streq(cap, "control_d"))
+                        break;
+        if (!cap) {
+                log_debug("Virtualization XEN DomU found (/proc/xen/capabilites)");
+                return false;
+        }
 
-        return cap ? VIRTUALIZATION_NONE : VIRTUALIZATION_XEN;
-                }
+        log_debug("Virtualization XEN Dom0 ignored (/proc/xen/capabilities)");
+        return true;
+}
 
 static int detect_vm_hypervisor(void) {
-                _cleanup_free_ char *hvtype = NULL;
+        _cleanup_free_ char *hvtype = NULL;
         int r;
 
-                r = read_one_line_file("/sys/hypervisor/type", &hvtype);
+        r = read_one_line_file("/sys/hypervisor/type", &hvtype);
         if (r == -ENOENT)
                 return VIRTUALIZATION_NONE;
         if (r < 0)
                 return r;
 
+        log_debug("Virtualization %s found in /sys/hypervisor/type", hvtype);
+
         if (streq(hvtype, "xen"))
                 return VIRTUALIZATION_XEN;
         else
@@ -235,9 +275,13 @@ static int detect_vm_uml(void) {
         r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
         if (r < 0)
                 return r;
-        if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n"))
+
+        if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
+                log_debug("UML virtualization found in /proc/cpuinfo");
                 return VIRTUALIZATION_UML;
+        }
 
+        log_debug("No virtualization found in /proc/cpuinfo.");
         return VIRTUALIZATION_NONE;
 }
 
@@ -253,14 +297,16 @@ static int detect_vm_zvm(void) {
         if (r < 0)
                 return r;
 
+        log_debug("Virtualization %s found in /proc/sysinfo", t);
         if (streq(t, "z/VM"))
                 return VIRTUALIZATION_ZVM;
         else
                 return VIRTUALIZATION_KVM;
 #else
+        log_debug("This platform does not support /proc/sysinfo");
         return VIRTUALIZATION_NONE;
 #endif
-        }
+}
 
 /* Returns a short identifier for the various VM implementations */
 int detect_vm(void) {
@@ -318,14 +364,21 @@ int detect_vm(void) {
         if (r < 0)
                 return r;
         if (r != VIRTUALIZATION_NONE)
-                        goto finish;
+                goto finish;
 
         r = detect_vm_zvm();
         if (r < 0)
                 return r;
 
 finish:
+        /* x86 xen Dom0 is detected as XEN in hypervisor and maybe others.
+         * In order to detect the Dom0 as not virtualization we need to
+         * double-check it */
+        if (r == VIRTUALIZATION_XEN && detect_vm_xen_dom0())
+                r = VIRTUALIZATION_NONE;
+
         cached_found = r;
+        log_debug("Found VM virtualization %s", virtualization_to_string(r));
         return r;
 }
 #endif // 0
@@ -414,6 +467,7 @@ int detect_container(void) {
         r = VIRTUALIZATION_CONTAINER_OTHER;
 
 finish:
+        log_debug("Found container virtualization %s", virtualization_to_string(r));
         cached_found = r;
         return r;
 }
@@ -423,10 +477,10 @@ int detect_virtualization(void) {
         int r;
 
         r = detect_container();
-        if (r != 0)
-                return r;
+        if (r == 0)
+                r = detect_vm();
 
-        return detect_vm();
+        return r;
 }
 #endif // 0
 
@@ -440,7 +494,6 @@ int running_in_chroot(void) {
         return ret == 0;
 }
 
-#if 0 /// UNNEEDED by elogind
 static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
         [VIRTUALIZATION_NONE] = "none",
         [VIRTUALIZATION_KVM] = "kvm",
@@ -465,4 +518,3 @@ static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(virtualization, int);
-#endif // 0
index 22dd815..1d88ab9 100644 (file)
@@ -72,7 +72,5 @@ int detect_virtualization(void);
 
 int running_in_chroot(void);
 
-#if 0 /// UNNEEDED by elogind
 const char *virtualization_to_string(int v) _const_;
 int virtualization_from_string(const char *s) _pure_;
-#endif // 0