From c733f9b08d9eadc5e671185112567ada81116bdf Mon Sep 17 00:00:00 2001 From: Sven Eden Date: Wed, 24 May 2017 13:51:31 +0200 Subject: [PATCH] Prep v230: Apply missing upstream fixes and updates (2/8) src/basic. --- src/basic/alloc-util.c | 4 + src/basic/cgroup-util.c | 98 +++++++++----- src/basic/cgroup-util.h | 42 ++++++ src/basic/copy.c | 70 +++++++--- src/basic/copy.h | 1 + src/basic/def.h | 2 - src/basic/escape.c | 28 ++++ src/basic/escape.h | 3 +- src/basic/fd-util.c | 14 ++ src/basic/fd-util.h | 2 + src/basic/fileio-label.h | 1 - src/basic/fileio.c | 134 +++++++++++++++----- src/basic/fileio.h | 11 +- src/basic/fs-util.c | 36 +++--- src/basic/fs-util.h | 11 +- src/basic/hash-funcs.c | 8 +- src/basic/hash-funcs.h | 8 +- src/basic/hashmap.c | 10 +- src/basic/hashmap.h | 2 + src/basic/hostname-util.c | 46 +++++-- src/basic/hostname-util.h | 2 + src/basic/log.c | 23 ++-- src/basic/log.h | 9 +- src/basic/login-util.h | 4 +- src/basic/memfd-util.c | 2 +- src/basic/memfd-util.h | 1 + src/basic/missing.h | 246 +----------------------------------- src/basic/missing_syscall.h | 12 +- src/basic/parse-util.c | 4 +- src/basic/parse-util.h | 1 - src/basic/path-util.c | 84 +++++++----- src/basic/path-util.h | 22 +++- src/basic/process-util.c | 22 +++- src/basic/process-util.h | 8 +- src/basic/rm-rf.c | 4 +- src/basic/selinux-util.c | 40 +++--- src/basic/selinux-util.h | 2 +- src/basic/siphash24.c | 54 ++++---- src/basic/socket-util.c | 110 ++++++++++++++++ src/basic/socket-util.h | 6 + src/basic/stdio-util.h | 4 - src/basic/strv.c | 2 +- src/basic/strv.h | 3 + src/basic/terminal-util.c | 19 ++- src/basic/time-util.c | 148 +++++++++++++--------- src/basic/time-util.h | 6 + src/basic/unit-name.c | 2 +- src/basic/util.c | 25 ++-- src/basic/util.h | 14 +- src/basic/virt.c | 96 ++++++++++---- src/basic/virt.h | 2 - 51 files changed, 896 insertions(+), 612 deletions(-) diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c index a16f97c3d..b540dcddf 100644 --- a/src/basic/alloc-util.c +++ b/src/basic/alloc-util.c @@ -17,7 +17,11 @@ along with systemd; If not, see . ***/ +#include +#include + #include "alloc-util.h" +#include "macro.h" #include "util.h" void* memdup(const void *p, size_t l) { diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 65909f9ef..3636f13da 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -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", diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 996fe595c..2ff438437 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -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 diff --git a/src/basic/copy.c b/src/basic/copy.c index c2c0579c8..66279cf92 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -46,14 +46,35 @@ //#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 */ diff --git a/src/basic/copy.h b/src/basic/copy.h index c389724aa..41aad741c 100644 --- a/src/basic/copy.h +++ b/src/basic/copy.h @@ -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 diff --git a/src/basic/def.h b/src/basic/def.h index 31753e600..bc7826f7b 100644 --- a/src/basic/def.h +++ b/src/basic/def.h @@ -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" \ diff --git a/src/basic/escape.c b/src/basic/escape.c index 564149306..127ca2ecb 100644 --- a/src/basic/escape.c +++ b/src/basic/escape.c @@ -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); diff --git a/src/basic/escape.h b/src/basic/escape.h index f57438038..8383c7586 100644 --- a/src/basic/escape.h +++ b/src/basic/escape.h @@ -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 diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c index 9c15b91c3..8e4cfe3fe 100644 --- a/src/basic/fd-util.c +++ b/src/basic/fd-util.c @@ -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 diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h index e2f5bbdaf..522ea6894 100644 --- a/src/basic/fd-util.h +++ b/src/basic/fd-util.h @@ -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 */ diff --git a/src/basic/fileio-label.h b/src/basic/fileio-label.h index 25262efb8..4deeef252 100644 --- a/src/basic/fileio-label.h +++ b/src/basic/fileio-label.h @@ -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, diff --git a/src/basic/fileio.c b/src/basic/fileio.c index da53c3e75..d3fb86174 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -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 diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 0635147b7..3c7b9c85b 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -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 diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index b37fef8f5..426ad9761 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -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 diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 2000b38a9..2c5a65026 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -30,11 +30,13 @@ #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 diff --git a/src/basic/hash-funcs.c b/src/basic/hash-funcs.c index d7b61ceae..c3a4a011b 100644 --- a/src/basic/hash-funcs.c +++ b/src/basic/hash-funcs.c @@ -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 . + along with systemd; If not, see . ***/ #include "hash-funcs.h" diff --git a/src/basic/hash-funcs.h b/src/basic/hash-funcs.h index 01be3ca70..299189d14 100644 --- a/src/basic/hash-funcs.h +++ b/src/basic/hash-funcs.h @@ -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 . + along with systemd; If not, see . ***/ #include "macro.h" diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index 75ea2e30b..c89630f04 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -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 diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h index a51027204..0fda53e11 100644 --- a/src/basic/hashmap.h +++ b/src/basic/hashmap.h @@ -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)); diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c index 3bd3a4d7b..d8d05df3c 100644 --- a/src/basic/hostname-util.c +++ b/src/basic/hostname-util.c @@ -17,9 +17,6 @@ along with systemd; If not, see . ***/ -#if defined(__GLIBC__) -# include -#endif // defined(__GLIBC__) #include #include #include @@ -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 diff --git a/src/basic/hostname-util.h b/src/basic/hostname-util.h index f22716d0e..1c9efabe1 100644 --- a/src/basic/hostname-util.h +++ b/src/basic/hostname-util.h @@ -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); diff --git a/src/basic/log.c b/src/basic/log.c index 08aa986a0..1b8374cfd 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -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); diff --git a/src/basic/log.h b/src/basic/log.h index 899474daa..0b82b768c 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -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 */ diff --git a/src/basic/login-util.h b/src/basic/login-util.h index 89a337d7c..b01ee25c8 100644 --- a/src/basic/login-util.h +++ b/src/basic/login-util.h @@ -1,3 +1,5 @@ +#pragma once + /*** This file is part of systemd. @@ -17,8 +19,6 @@ along with systemd; If not, see . ***/ -#pragma once - #include #include diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c index 66b5e5c7b..e857c040d 100644 --- a/src/basic/memfd-util.c +++ b/src/basic/memfd-util.c @@ -22,7 +22,7 @@ #include #include #ifdef HAVE_LINUX_MEMFD_H -# include +#include #endif #include #include diff --git a/src/basic/memfd-util.h b/src/basic/memfd-util.h index 419d89979..6b828520e 100644 --- a/src/basic/memfd-util.h +++ b/src/basic/memfd-util.h @@ -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); diff --git a/src/basic/missing.h b/src/basic/missing.h index 7948fc176..984a4c0ed 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -137,84 +137,6 @@ #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" diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h index 42c39ee8d..abfe62a5e 100644 --- a/src/basic/missing_syscall.h +++ b/src/basic/missing_syscall.h @@ -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 . + along with systemd; If not, see . ***/ /* 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 /* ======================================================================= */ diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c index 63732634a..d0208e93f 100644 --- a/src/basic/parse-util.c +++ b/src/basic/parse-util.c @@ -23,7 +23,9 @@ #include #include #include -//#include +#if defined(__GLIBC__) +# include +#endif // defined(__GLIBC__) #include "alloc-util.h" //#include "extract-word.h" diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h index ea70c5e1e..250f887f4 100644 --- a/src/basic/parse-util.h +++ b/src/basic/parse-util.h @@ -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); diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 5f4252f48..123b4ce8c 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -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 diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 99035aae9..540a69c62 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -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); diff --git a/src/basic/process-util.c b/src/basic/process-util.c index d146638b8..f418b85b9 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -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); diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 66b6cd13a..6cf3a40b1 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -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); diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c index 6912b23f5..474bfbf43 100644 --- a/src/basic/rm-rf.c +++ b/src/basic/rm-rf.c @@ -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); diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c index 700b2e829..835d3fd43 100644 --- a/src/basic/selinux-util.c +++ b/src/basic/selinux-util.c @@ -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; diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h index e2d21a486..0528b7759 100644 --- a/src/basic/selinux-util.h +++ b/src/basic/selinux-util.h @@ -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 diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c index 8edaae511..060e8ba38 100644 --- a/src/basic/siphash24.c +++ b/src/basic/siphash24.c @@ -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); diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 73e19310e..5efd09fb8 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -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 diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 8850d9f16..b5d1dc3ed 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -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) \ diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h index 757c10591..bd1144b4c 100644 --- a/src/basic/stdio-util.h +++ b/src/basic/stdio-util.h @@ -19,11 +19,7 @@ along with systemd; If not, see . ***/ -#if defined(__GLIBC__) && defined(HAVE_PRINTF_H) #include -#else -#include "parse-printf-format.h" -#endif #include #include #include diff --git a/src/basic/strv.c b/src/basic/strv.c index 7757a4443..93bb130ea 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -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; } diff --git a/src/basic/strv.h b/src/basic/strv.h index 8e83ffde7..591a452e9 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -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)++) diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 75a0d6fd8..cb1e6a019 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -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; } diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 2a3957d97..97db1e2cc 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -44,10 +44,30 @@ 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; diff --git a/src/basic/time-util.h b/src/basic/time-util.h index 3c3fcca57..6feb75cc7 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -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 diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c index 6e6bd3bdb..463301eeb 100644 --- a/src/basic/unit-name.c +++ b/src/basic/unit-name.c @@ -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; } } diff --git a/src/basic/util.c b/src/basic/util.c index 68097b46a..1ef6f5f2b 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -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; } diff --git a/src/basic/util.h b/src/basic/util.h index 1fe660b62..af5a4fc9e 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -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); diff --git a/src/basic/virt.c b/src/basic/virt.c index 6eb1d0c46..0c0820103 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -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 diff --git a/src/basic/virt.h b/src/basic/virt.h index 22dd815f3..1d88ab9ab 100644 --- a/src/basic/virt.h +++ b/src/basic/virt.h @@ -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 -- 2.30.2