diff options
Diffstat (limited to 'src/basic')
44 files changed, 292 insertions, 232 deletions
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h index ff7a46793a..893a1238ff 100644 --- a/src/basic/alloc-util.h +++ b/src/basic/alloc-util.h @@ -10,20 +10,28 @@ typedef void (*free_func_t)(void *p); +/* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than + * proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */ +#define ALLOCA_MAX (4U*1024U*1024U) + #define new(t, n) ((t*) malloc_multiply(sizeof(t), (n))) #define new0(t, n) ((t*) calloc((n) ?: 1, sizeof(t))) -#define newa(t, n) \ - ({ \ - assert(!size_multiply_overflow(sizeof(t), n)); \ - (t*) alloca(sizeof(t)*(n)); \ +#define newa(t, n) \ + ({ \ + size_t _n_ = n; \ + assert(!size_multiply_overflow(sizeof(t), _n_)); \ + assert(sizeof(t)*_n_ <= ALLOCA_MAX); \ + (t*) alloca(sizeof(t)*_n_); \ }) -#define newa0(t, n) \ - ({ \ - assert(!size_multiply_overflow(sizeof(t), n)); \ - (t*) alloca0(sizeof(t)*(n)); \ +#define newa0(t, n) \ + ({ \ + size_t _n_ = n; \ + assert(!size_multiply_overflow(sizeof(t), _n_)); \ + assert(sizeof(t)*_n_ <= ALLOCA_MAX); \ + (t*) alloca0(sizeof(t)*_n_); \ }) #define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n))) @@ -51,16 +59,20 @@ void* memdup_suffix0(const void *p, size_t l) _alloc_(2); #define memdupa(p, l) \ ({ \ void *_q_; \ - _q_ = alloca(l); \ - memcpy(_q_, p, l); \ + size_t _l_ = l; \ + assert(_l_ <= ALLOCA_MAX); \ + _q_ = alloca(_l_); \ + memcpy(_q_, p, _l_); \ }) #define memdupa_suffix0(p, l) \ ({ \ void *_q_; \ - _q_ = alloca(l + 1); \ - ((uint8_t*) _q_)[l] = 0; \ - memcpy(_q_, p, l); \ + size_t _l_ = l; \ + assert(_l_ <= ALLOCA_MAX); \ + _q_ = alloca(_l_ + 1); \ + ((uint8_t*) _q_)[_l_] = 0; \ + memcpy(_q_, p, _l_); \ }) static inline void freep(void *p) { @@ -116,6 +128,7 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); ({ \ char *_new_; \ size_t _len_ = n; \ + assert(_len_ <= ALLOCA_MAX); \ _new_ = alloca(_len_); \ (void *) memset(_new_, 0, _len_); \ }) @@ -125,16 +138,18 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); ({ \ void *_ptr_; \ size_t _mask_ = (align) - 1; \ - _ptr_ = alloca((size) + _mask_); \ + size_t _size_ = size; \ + assert(_size_ <= ALLOCA_MAX); \ + _ptr_ = alloca(_size_ + _mask_); \ (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ }) #define alloca0_align(size, align) \ ({ \ void *_new_; \ - size_t _size_ = (size); \ - _new_ = alloca_align(_size_, (align)); \ - (void*)memset(_new_, 0, _size_); \ + size_t _xsize_ = (size); \ + _new_ = alloca_align(_xsize_, (align)); \ + (void*)memset(_new_, 0, _xsize_); \ }) /* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c index d08e7546d0..da4dd2a827 100644 --- a/src/basic/btrfs-util.c +++ b/src/basic/btrfs-util.c @@ -941,7 +941,7 @@ int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid) { /* Destroys the specified qgroup, but unassigns it from all * its parents first. Also, it recursively destroys all - * qgroups it is assgined to that have the same id part of the + * qgroups it is assigned to that have the same id part of the * qgroupid as the specified group. */ r = btrfs_qgroupid_split(qgroupid, NULL, &subvol_id); diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h index 085aca4dbc..7d848a75d3 100644 --- a/src/basic/btrfs-util.h +++ b/src/basic/btrfs-util.h @@ -28,17 +28,17 @@ typedef struct BtrfsQuotaInfo { } BtrfsQuotaInfo; typedef enum BtrfsSnapshotFlags { - BTRFS_SNAPSHOT_FALLBACK_COPY = 1, /* If the source isn't a subvolume, reflink everything */ - BTRFS_SNAPSHOT_READ_ONLY = 2, - BTRFS_SNAPSHOT_RECURSIVE = 4, - BTRFS_SNAPSHOT_QUOTA = 8, - BTRFS_SNAPSHOT_FALLBACK_DIRECTORY = 16, /* If the destination doesn't support subvolumes, reflink/copy instead */ - BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE = 32, /* When we can't create a subvolume, use the FS_IMMUTABLE attribute for indicating read-only */ + BTRFS_SNAPSHOT_FALLBACK_COPY = 1 << 0, /* If the source isn't a subvolume, reflink everything */ + BTRFS_SNAPSHOT_READ_ONLY = 1 << 1, + BTRFS_SNAPSHOT_RECURSIVE = 1 << 2, + BTRFS_SNAPSHOT_QUOTA = 1 << 3, + BTRFS_SNAPSHOT_FALLBACK_DIRECTORY = 1 << 4, /* If the destination doesn't support subvolumes, reflink/copy instead */ + BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE = 1 << 5, /* When we can't create a subvolume, use the FS_IMMUTABLE attribute for indicating read-only */ } BtrfsSnapshotFlags; typedef enum BtrfsRemoveFlags { - BTRFS_REMOVE_RECURSIVE = 1, - BTRFS_REMOVE_QUOTA = 2, + BTRFS_REMOVE_RECURSIVE = 1 << 0, + BTRFS_REMOVE_QUOTA = 1 << 1, } BtrfsRemoveFlags; int btrfs_is_filesystem(int fd); diff --git a/src/basic/build.h b/src/basic/build.h index 2c46550300..7a59059080 100644 --- a/src/basic/build.h +++ b/src/basic/build.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include "version.h" + #if HAVE_PAM #define _PAM_FEATURE_ "+PAM" #else diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c index a3f3ca9f52..b944ee6ea1 100644 --- a/src/basic/capability-util.c +++ b/src/basic/capability-util.c @@ -13,6 +13,7 @@ #include "fileio.h" #include "log.h" #include "macro.h" +#include "missing_prctl.h" #include "parse-util.h" #include "user-util.h" #include "util.h" diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 830a63c185..8ce7ccb960 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -872,7 +872,7 @@ int cg_set_access( bool fatal; }; - /* cgroupsv1, aka legacy/non-unified */ + /* cgroup v1, aka legacy/non-unified */ static const struct Attribute legacy_attributes[] = { { "cgroup.procs", true }, { "tasks", false }, @@ -880,7 +880,7 @@ int cg_set_access( {}, }; - /* cgroupsv2, aka unified */ + /* cgroup v2, aka unified */ static const struct Attribute unified_attributes[] = { { "cgroup.procs", true }, { "cgroup.subtree_control", true }, @@ -2039,7 +2039,7 @@ int cg_get_keyed_attribute( char **v; int r; - /* Reads one or more fields of a cgroupsv2 keyed attribute file. The 'keys' parameter should be an strv with + /* Reads one or more fields of a cgroup v2 keyed attribute file. The 'keys' parameter should be an strv with * all keys to retrieve. The 'ret_values' parameter should be passed as string size with the same number of * entries as 'keys'. On success each entry will be set to the value of the matching key. * @@ -2491,7 +2491,7 @@ int cg_kernel_controllers(Set **ret) { static thread_local CGroupUnified unified_cache = CGROUP_UNIFIED_UNKNOWN; -/* The hybrid mode was initially implemented in v232 and simply mounted cgroup v2 on /sys/fs/cgroup/systemd. This +/* The hybrid mode was initially implemented in v232 and simply mounted cgroup2 on /sys/fs/cgroup/systemd. This * unfortunately broke other tools (such as docker) which expected the v1 "name=systemd" hierarchy on * /sys/fs/cgroup/systemd. From v233 and on, the hybrid mode mountnbs v2 on /sys/fs/cgroup/unified and maintains * "name=systemd" hierarchy on /sys/fs/cgroup/systemd for compatibility with other tools. @@ -2739,13 +2739,13 @@ bool cg_is_legacy_wanted(void) { if (wanted >= 0) return wanted; - /* Check if we have cgroups2 already mounted. */ + /* Check if we have cgroup v2 already mounted. */ if (cg_unified_flush() >= 0 && unified_cache == CGROUP_UNIFIED_ALL) return (wanted = false); /* Otherwise, assume that at least partial legacy is wanted, - * since cgroups2 should already be mounted at this point. */ + * since cgroup v2 should already be mounted at this point. */ return (wanted = true); } diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index ea9a333290..119b493dc6 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -48,13 +48,13 @@ typedef enum CGroupMask { CGROUP_MASK_BPF_FIREWALL = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_FIREWALL), CGROUP_MASK_BPF_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_DEVICES), - /* All real cgroupv1 controllers */ + /* All real cgroup v1 controllers */ CGROUP_MASK_V1 = CGROUP_MASK_CPU|CGROUP_MASK_CPUACCT|CGROUP_MASK_BLKIO|CGROUP_MASK_MEMORY|CGROUP_MASK_DEVICES|CGROUP_MASK_PIDS, - /* All real cgroupv2 controllers */ + /* All real cgroup v2 controllers */ CGROUP_MASK_V2 = CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_MEMORY|CGROUP_MASK_PIDS, - /* All cgroupv2 BPF pseudo-controllers */ + /* All cgroup v2 BPF pseudo-controllers */ CGROUP_MASK_BPF = CGROUP_MASK_BPF_FIREWALL|CGROUP_MASK_BPF_DEVICES, _CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1 @@ -162,9 +162,9 @@ int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d); int cg_read_subgroup(DIR *d, char **fn); typedef enum CGroupFlags { - CGROUP_SIGCONT = 1, - CGROUP_IGNORE_SELF = 2, - CGROUP_REMOVE = 4, + CGROUP_SIGCONT = 1 << 0, + CGROUP_IGNORE_SELF = 1 << 1, + CGROUP_REMOVE = 1 << 2, } CGroupFlags; typedef void (*cg_kill_log_func_t)(pid_t pid, int sig, void *userdata); diff --git a/src/basic/copy.c b/src/basic/copy.c index 34e01ea1cf..46e02a3759 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -24,6 +24,7 @@ #include "macro.h" #include "missing.h" #include "mountpoint-util.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" @@ -501,7 +502,7 @@ static int fd_copy_directory( _cleanup_close_ int fdf = -1, fdt = -1; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; - bool created; + bool exists, created; int r; assert(st); @@ -522,13 +523,26 @@ static int fd_copy_directory( return -errno; fdf = -1; - r = mkdirat(dt, to, st->st_mode & 07777); - if (r >= 0) - created = true; - else if (errno == EEXIST && (copy_flags & COPY_MERGE)) + exists = false; + if (copy_flags & COPY_MERGE_EMPTY) { + r = dir_is_empty_at(dt, to); + if (r < 0 && r != -ENOENT) + return r; + else if (r == 1) + exists = true; + } + + if (exists) created = false; - else - return -errno; + else { + r = mkdirat(dt, to, st->st_mode & 07777); + if (r >= 0) + created = true; + else if (errno == EEXIST && (copy_flags & COPY_MERGE)) + created = false; + else + return -errno; + } fdt = openat(dt, to, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fdt < 0) diff --git a/src/basic/copy.h b/src/basic/copy.h index a41b44c70a..f677021881 100644 --- a/src/basic/copy.h +++ b/src/basic/copy.h @@ -9,10 +9,11 @@ #include <sys/types.h> typedef enum CopyFlags { - COPY_REFLINK = 1 << 0, /* Try to reflink */ - COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */ - COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */ - COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */ + COPY_REFLINK = 1 << 0, /* Try to reflink */ + COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */ + COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */ + COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */ + COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */ } CopyFlags; typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, void *userdata); diff --git a/src/basic/env-file.c b/src/basic/env-file.c index 6a7d6746a1..7f10f9ad39 100644 --- a/src/basic/env-file.c +++ b/src/basic/env-file.c @@ -35,7 +35,6 @@ static int parse_env_file_internal( VALUE, VALUE_ESCAPE, SINGLE_QUOTE_VALUE, - SINGLE_QUOTE_VALUE_ESCAPE, DOUBLE_QUOTE_VALUE, DOUBLE_QUOTE_VALUE_ESCAPE, COMMENT, @@ -113,7 +112,7 @@ static int parse_env_file_internal( } else if (c == '\'') state = SINGLE_QUOTE_VALUE; - else if (c == '\"') + else if (c == '"') state = DOUBLE_QUOTE_VALUE; else if (c == '\\') state = VALUE_ESCAPE; @@ -186,8 +185,6 @@ static int parse_env_file_internal( case SINGLE_QUOTE_VALUE: if (c == '\'') state = PRE_VALUE; - else if (c == '\\') - state = SINGLE_QUOTE_VALUE_ESCAPE; else { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; @@ -197,19 +194,8 @@ static int parse_env_file_internal( break; - case SINGLE_QUOTE_VALUE_ESCAPE: - state = SINGLE_QUOTE_VALUE; - - if (!strchr(NEWLINE, c)) { - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; - - value[n_value++] = c; - } - break; - case DOUBLE_QUOTE_VALUE: - if (c == '\"') + if (c == '"') state = PRE_VALUE; else if (c == '\\') state = DOUBLE_QUOTE_VALUE_ESCAPE; @@ -225,12 +211,17 @@ static int parse_env_file_internal( case DOUBLE_QUOTE_VALUE_ESCAPE: state = DOUBLE_QUOTE_VALUE; - if (!strchr(NEWLINE, c)) { + if (c == '"') { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) return -ENOMEM; - + value[n_value++] = '"'; + } else if (!strchr(NEWLINE, c)) { + if (!GREEDY_REALLOC(value, value_alloc, n_value+3)) + return -ENOMEM; + value[n_value++] = '\\'; value[n_value++] = c; } + break; case COMMENT: @@ -253,7 +244,6 @@ static int parse_env_file_internal( VALUE, VALUE_ESCAPE, SINGLE_QUOTE_VALUE, - SINGLE_QUOTE_VALUE_ESCAPE, DOUBLE_QUOTE_VALUE, DOUBLE_QUOTE_VALUE_ESCAPE)) { @@ -527,7 +517,7 @@ static void write_env_var(FILE *f, const char *v) { fwrite_unlocked(v, 1, p-v, f); if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) { - fputc_unlocked('\"', f); + fputc_unlocked('"', f); for (; *p; p++) { if (strchr(SHELL_NEED_ESCAPE, *p)) @@ -536,7 +526,7 @@ static void write_env_var(FILE *f, const char *v) { fputc_unlocked(*p, f); } - fputc_unlocked('\"', f); + fputc_unlocked('"', f); } else fputs_unlocked(p, f); diff --git a/src/basic/env-util.c b/src/basic/env-util.c index e494f65c98..fd449dcce0 100644 --- a/src/basic/env-util.c +++ b/src/basic/env-util.c @@ -339,7 +339,6 @@ char **strv_env_unset(char **l, const char *p) { } char **strv_env_unset_many(char **l, ...) { - char **f, **t; if (!l) @@ -408,7 +407,6 @@ int strv_env_replace(char ***l, char *p) { } char **strv_env_set(char **x, const char *p) { - _cleanup_strv_free_ char **ret = NULL; size_t n, m; char **k; diff --git a/src/basic/env-util.h b/src/basic/env-util.h index 4d21ea6bef..d54f99658b 100644 --- a/src/basic/env-util.h +++ b/src/basic/env-util.h @@ -13,9 +13,9 @@ bool env_value_is_valid(const char *e); bool env_assignment_is_valid(const char *e); enum { - REPLACE_ENV_USE_ENVIRONMENT = 1u, - REPLACE_ENV_ALLOW_BRACELESS = 2u, - REPLACE_ENV_ALLOW_EXTENDED = 4u, + REPLACE_ENV_USE_ENVIRONMENT = 1 << 0, + REPLACE_ENV_ALLOW_BRACELESS = 1 << 1, + REPLACE_ENV_ALLOW_EXTENDED = 1 << 2, }; char *replace_env_n(const char *format, size_t n, char **env, unsigned flags); diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h index 8c63b7c306..705ebbe95b 100644 --- a/src/basic/extract-word.h +++ b/src/basic/extract-word.h @@ -4,12 +4,12 @@ #include "macro.h" typedef enum ExtractFlags { - EXTRACT_RELAX = 1, - EXTRACT_CUNESCAPE = 2, - EXTRACT_CUNESCAPE_RELAX = 4, - EXTRACT_QUOTES = 8, - EXTRACT_DONT_COALESCE_SEPARATORS = 16, - EXTRACT_RETAIN_ESCAPE = 32, + EXTRACT_RELAX = 1 << 0, + EXTRACT_CUNESCAPE = 1 << 1, + EXTRACT_CUNESCAPE_RELAX = 1 << 2, + EXTRACT_QUOTES = 1 << 3, + EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 4, + EXTRACT_RETAIN_ESCAPE = 1 << 5, } ExtractFlags; int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags); diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c index c06f2fac7e..3e6ef5a06a 100644 --- a/src/basic/fd-util.c +++ b/src/basic/fd-util.c @@ -70,7 +70,7 @@ int safe_close(int fd) { return -1; } -void safe_close_pair(int p[]) { +void safe_close_pair(int p[static 2]) { assert(p); if (p[0] == p[1]) { @@ -189,6 +189,27 @@ _pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) { return false; } +static int get_max_fd(void) { + struct rlimit rl; + rlim_t m; + + /* Return the highest possible fd, based RLIMIT_NOFILE, but enforcing FD_SETSIZE-1 as lower boundary + * and INT_MAX as upper boundary. */ + + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) + return -errno; + + m = MAX(rl.rlim_cur, rl.rlim_max); + if (m < FD_SETSIZE) /* Let's always cover at least 1024 fds */ + return FD_SETSIZE-1; + + if (m == RLIM_INFINITY || m > INT_MAX) /* Saturate on overflow. After all fds are "int", hence can + * never be above INT_MAX */ + return INT_MAX; + + return (int) (m - 1); +} + int close_all_fds(const int except[], size_t n_except) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; @@ -198,20 +219,14 @@ int close_all_fds(const int except[], size_t n_except) { d = opendir("/proc/self/fd"); if (!d) { - struct rlimit rl; int fd, max_fd; - /* When /proc isn't available (for example in chroots) the fallback is brute forcing through the fd - * table */ - - assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0); - - if (rl.rlim_max == 0) - return -EINVAL; + /* When /proc isn't available (for example in chroots) the fallback is brute forcing through + * the fd table */ - /* Let's take special care if the resource limit is set to unlimited, or actually larger than the range - * of 'int'. Let's avoid implicit overflows. */ - max_fd = (rl.rlim_max == RLIM_INFINITY || rl.rlim_max > INT_MAX) ? INT_MAX : (int) (rl.rlim_max - 1); + max_fd = get_max_fd(); + if (max_fd < 0) + return max_fd; for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) { int q; diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h index 00303a7e45..4085a244d2 100644 --- a/src/basic/fd-util.h +++ b/src/basic/fd-util.h @@ -14,7 +14,7 @@ int close_nointr(int fd); int safe_close(int fd); -void safe_close_pair(int p[]); +void safe_close_pair(int p[static 2]); static inline int safe_close_above_stdio(int fd) { if (fd < 3) /* Don't close stdin/stdout/stderr, but still invalidate the fd by returning -1 */ diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index 5a4bb37b82..66e9e0046b 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -345,7 +345,7 @@ static unsigned base_bucket_hash(HashmapBase *h, const void *p) { } #define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p) -static inline void base_set_dirty(HashmapBase *h) { +static void base_set_dirty(HashmapBase *h) { h->dirty = true; } #define hashmap_set_dirty(h) base_set_dirty(HASHMAP_BASE(h)) @@ -888,7 +888,8 @@ void internal_hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_f * themselves from our hash table a second time, the entry is already gone. */ while (internal_hashmap_size(h) > 0) { - void *v, *k; + void *k = NULL; + void *v; v = internal_hashmap_first_key_and_value(h, true, &k); @@ -1515,8 +1516,11 @@ void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **r unsigned idx; idx = find_first_entry(h); - if (idx == IDX_NIL) + if (idx == IDX_NIL) { + if (ret_key) + *ret_key = NULL; return NULL; + } e = bucket_at(h, idx); key = (void*) e->key; diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h index 5bf807a76f..e16a9f9e30 100644 --- a/src/basic/hashmap.h +++ b/src/basic/hashmap.h @@ -326,7 +326,6 @@ static inline void *ordered_hashmap_first_key_and_value(OrderedHashmap *h, void return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret); } - static inline void *hashmap_steal_first(Hashmap *h) { return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL); } diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c index 411efb242b..2bffe473ca 100644 --- a/src/basic/in-addr-util.c +++ b/src/basic/in-addr-util.c @@ -495,9 +495,8 @@ int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) { return 0; } -int in_addr_prefix_from_string_internal( +int in_addr_prefix_from_string( const char *p, - bool use_default_prefixlen, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { @@ -531,13 +530,6 @@ int in_addr_prefix_from_string_internal( r = in_addr_parse_prefixlen(family, e+1, &k); if (r < 0) return r; - } else if (use_default_prefixlen) { - if (family == AF_INET) { - r = in4_addr_default_prefixlen(&buffer.in, &k); - if (r < 0) - return r; - } else - k = 0; } else k = FAMILY_ADDRESS_SIZE(family) * 8; @@ -551,7 +543,7 @@ int in_addr_prefix_from_string_internal( int in_addr_prefix_from_string_auto_internal( const char *p, - bool use_default_prefixlen, + InAddrPrefixLenMode mode, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { @@ -582,15 +574,24 @@ int in_addr_prefix_from_string_auto_internal( r = in_addr_parse_prefixlen(family, e+1, &k); if (r < 0) return r; - } else if (use_default_prefixlen) { - if (family == AF_INET) { - r = in4_addr_default_prefixlen(&buffer.in, &k); - if (r < 0) - return r; - } else - k = 0; } else - k = FAMILY_ADDRESS_SIZE(family) * 8; + switch (mode) { + case PREFIXLEN_FULL: + k = FAMILY_ADDRESS_SIZE(family) * 8; + break; + case PREFIXLEN_REFUSE: + return -ENOANO; /* To distinguish this error from others. */ + case PREFIXLEN_LEGACY: + if (family == AF_INET) { + r = in4_addr_default_prefixlen(&buffer.in, &k); + if (r < 0) + return r; + } else + k = 0; + break; + default: + assert_not_reached("Invalid prefixlen mode"); + } if (ret_family) *ret_family = family; diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h index 5de85cc422..3069790519 100644 --- a/src/basic/in-addr-util.h +++ b/src/basic/in-addr-util.h @@ -45,19 +45,17 @@ int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mas int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen); int in_addr_prefix_covers(int family, const union in_addr_union *prefix, unsigned char prefixlen, const union in_addr_union *address); int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret); -int in_addr_prefix_from_string_internal(const char *p, bool use_default_prefixlen, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); -int in_addr_prefix_from_string_auto_internal(const char *p, bool use_default_prefixlen, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); -static inline int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { - return in_addr_prefix_from_string_internal(p, false, family, ret_prefix, ret_prefixlen); -} +int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); + +typedef enum InAddrPrefixLenMode { + PREFIXLEN_FULL, /* Default to prefixlen of address size, 32 for IPv4 or 128 for IPv6, if not specified. */ + PREFIXLEN_REFUSE, /* Fail with -ENOANO if prefixlen is not specified. */ + PREFIXLEN_LEGACY, /* Default to legacy default prefixlen calculation from address if not specified. */ +} InAddrPrefixLenMode; + +int in_addr_prefix_from_string_auto_internal(const char *p, InAddrPrefixLenMode mode, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); static inline int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { - return in_addr_prefix_from_string_auto_internal(p, false, ret_family, ret_prefix, ret_prefixlen); -} -static inline int in_addr_default_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { - return in_addr_prefix_from_string_internal(p, true, family, ret_prefix, ret_prefixlen); -} -static inline int in_addr_default_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { - return in_addr_prefix_from_string_auto_internal(p, true, ret_family, ret_prefix, ret_prefixlen); + return in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_FULL, ret_family, ret_prefix, ret_prefixlen); } static inline size_t FAMILY_ADDRESS_SIZE(int family) { diff --git a/src/basic/io-util.c b/src/basic/io-util.c index 1f64cc933b..575398fbe6 100644 --- a/src/basic/io-util.c +++ b/src/basic/io-util.c @@ -8,6 +8,7 @@ #include <unistd.h> #include "io-util.h" +#include "string-util.h" #include "time-util.h" int flush_fd(int fd) { @@ -252,3 +253,12 @@ ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) { return q - (const uint8_t*) p; } + +char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value) { + char *x; + + x = strappend(field, value); + if (x) + iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(x); + return x; +} diff --git a/src/basic/io-util.h b/src/basic/io-util.h index ed189b5820..792a64ad5e 100644 --- a/src/basic/io-util.h +++ b/src/basic/io-util.h @@ -71,3 +71,5 @@ static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) { #define IOVEC_MAKE(base, len) (struct iovec) IOVEC_INIT(base, len) #define IOVEC_INIT_STRING(string) IOVEC_INIT((char*) string, strlen(string)) #define IOVEC_MAKE_STRING(string) (struct iovec) IOVEC_INIT_STRING(string) + +char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value); diff --git a/src/basic/meson.build b/src/basic/meson.build index 23b5e75bd8..e5852f32f9 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -292,7 +292,8 @@ libbasic = static_library( 'basic', basic_sources, include_directories : includes, - dependencies : [threads, + dependencies : [versiondep, + threads, libcap, libselinux, libm], diff --git a/src/basic/missing_if_link.h b/src/basic/missing_if_link.h index 07675426bb..761797f56a 100644 --- a/src/basic/missing_if_link.h +++ b/src/basic/missing_if_link.h @@ -110,6 +110,9 @@ enum ipvlan_mode { #define IFLA_MAX 51 #endif +#if !HAVE_IFLA_BOND_MODE /* linux@90af231106c0b8d223c27d35464af95cb3d9cacf (3.13) */ +#define IFLA_BOND_MODE 1 +#endif #if !HAVE_IFLA_BOND_ACTIVE_SLAVE /* linux@ec76aa49855f6d6fea5e01de179fb57dd47c619d (3.13) */ #define IFLA_BOND_ACTIVE_SLAVE 2 #endif diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h index d5d4b26acb..d1aa32218b 100644 --- a/src/basic/missing_syscall.h +++ b/src/basic/missing_syscall.h @@ -3,6 +3,7 @@ /* Missing glibc definitions to access certain kernel APIs */ +#include <errno.h> #include <fcntl.h> #include <sys/syscall.h> #include <sys/types.h> diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 094aa47c01..86c5a577cb 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -131,7 +131,7 @@ char *prefix_root(const char *root, const char *path); _ret = _path; \ else { \ _l = strlen(_root) + 1 + strlen(_path) + 1; \ - _n = alloca(_l); \ + _n = newa(char, _l); \ _p = stpcpy(_n, _root); \ while (_p > _n && _p[-1] == '/') \ _p--; \ diff --git a/src/basic/prioq.c b/src/basic/prioq.c index cfd08d5d23..76b27fa0a8 100644 --- a/src/basic/prioq.c +++ b/src/basic/prioq.c @@ -259,15 +259,14 @@ int prioq_reshuffle(Prioq *q, void *data, unsigned *idx) { return 1; } -void *prioq_peek(Prioq *q) { - +void *prioq_peek_by_index(Prioq *q, unsigned idx) { if (!q) return NULL; - if (q->n_items <= 0) + if (idx >= q->n_items) return NULL; - return q->items[0].data; + return q->items[idx].data; } void *prioq_pop(Prioq *q) { diff --git a/src/basic/prioq.h b/src/basic/prioq.h index bba5c7caa4..1fb57bfa4c 100644 --- a/src/basic/prioq.h +++ b/src/basic/prioq.h @@ -19,8 +19,14 @@ int prioq_put(Prioq *q, void *data, unsigned *idx); int prioq_remove(Prioq *q, void *data, unsigned *idx); int prioq_reshuffle(Prioq *q, void *data, unsigned *idx); -void *prioq_peek(Prioq *q) _pure_; +void *prioq_peek_by_index(Prioq *q, unsigned idx) _pure_; +static inline void *prioq_peek(Prioq *q) { + return prioq_peek_by_index(q, 0); +} void *prioq_pop(Prioq *q); +#define PRIOQ_FOREACH_ITEM(q, p) \ + for (unsigned _i = 0; (p = prioq_peek_by_index(q, _i)); _i++) + unsigned prioq_size(Prioq *q) _pure_; bool prioq_isempty(Prioq *q) _pure_; diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 448503409b..78ce43b944 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -102,7 +102,8 @@ int get_process_comm(pid_t pid, char **ret) { int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) { _cleanup_fclose_ FILE *f = NULL; bool space = false; - char *k, *ans = NULL; + char *k; + _cleanup_free_ char *ans = NULL; const char *p; int c; @@ -129,6 +130,13 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + if (max_length == 0) { + /* This is supposed to be a safety guard against runaway command lines. */ + long l = sysconf(_SC_ARG_MAX); + assert(l > 0); + max_length = l; + } + if (max_length == 1) { /* If there's only room for one byte, return the empty string */ @@ -136,35 +144,9 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * if (!ans) return -ENOMEM; - *line = ans; + *line = TAKE_PTR(ans); return 0; - } else if (max_length == 0) { - size_t len = 0, allocated = 0; - - while ((c = getc(f)) != EOF) { - - if (!GREEDY_REALLOC(ans, allocated, len+3)) { - free(ans); - return -ENOMEM; - } - - if (isprint(c)) { - if (space) { - ans[len++] = ' '; - space = false; - } - - ans[len++] = c; - } else if (len > 0) - space = true; - } - - if (len > 0) - ans[len] = '\0'; - else - ans = mfree(ans); - } else { bool dotdotdot = false; size_t left; @@ -227,7 +209,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * _cleanup_free_ char *t = NULL; int h; - free(ans); + ans = mfree(ans); if (!comm_fallback) return -ENOENT; @@ -236,37 +218,42 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * if (h < 0) return h; - if (max_length == 0) - ans = strjoin("[", t, "]"); - else { - size_t l; - - l = strlen(t); + size_t l = strlen(t); - if (l + 3 <= max_length) - ans = strjoin("[", t, "]"); - else if (max_length <= 6) { + if (l + 3 <= max_length) { + ans = strjoin("[", t, "]"); + if (!ans) + return -ENOMEM; - ans = new(char, max_length); - if (!ans) - return -ENOMEM; + } else if (max_length <= 6) { + ans = new(char, max_length); + if (!ans) + return -ENOMEM; - memcpy(ans, "[...]", max_length-1); - ans[max_length-1] = 0; - } else { - t[max_length - 6] = 0; + memcpy(ans, "[...]", max_length-1); + ans[max_length-1] = 0; + } else { + t[max_length - 6] = 0; - /* Chop off final spaces */ - delete_trailing_chars(t, WHITESPACE); + /* Chop off final spaces */ + delete_trailing_chars(t, WHITESPACE); - ans = strjoin("[", t, "...]"); - } + ans = strjoin("[", t, "...]"); + if (!ans) + return -ENOMEM; } - if (!ans) - return -ENOMEM; + + *line = TAKE_PTR(ans); + return 0; } - *line = ans; + k = realloc(ans, strlen(ans) + 1); + if (!k) + return -ENOMEM; + + ans = NULL; + *line = k; + return 0; } diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 496e14d3de..c85ea30ecc 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -24,8 +24,8 @@ if (_pid_ == 0) { \ _r_ = ("/proc/self/" field); \ } else { \ - _r_ = alloca(STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \ - sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \ + _r_ = newa(char, STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \ + sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \ } \ _r_; \ }) diff --git a/src/basic/procfs-util.c b/src/basic/procfs-util.c index a159e344b3..7aaf95bfce 100644 --- a/src/basic/procfs-util.c +++ b/src/basic/procfs-util.c @@ -201,13 +201,11 @@ int procfs_cpu_get_usage(nsec_t *ret) { return 0; } -int procfs_memory_get_current(uint64_t *ret) { +int procfs_memory_get(uint64_t *ret_total, uint64_t *ret_used) { uint64_t mem_total = UINT64_MAX, mem_free = UINT64_MAX; _cleanup_fclose_ FILE *f = NULL; int r; - assert(ret); - f = fopen("/proc/meminfo", "re"); if (!f) return -errno; @@ -262,6 +260,9 @@ int procfs_memory_get_current(uint64_t *ret) { if (mem_free > mem_total) return -EINVAL; - *ret = (mem_total - mem_free) * 1024U; + if (ret_total) + *ret_total = mem_total * 1024U; + if (ret_used) + *ret_used = (mem_total - mem_free) * 1024U; return 0; } diff --git a/src/basic/procfs-util.h b/src/basic/procfs-util.h index f697ed92bc..5a44e9eff7 100644 --- a/src/basic/procfs-util.h +++ b/src/basic/procfs-util.h @@ -11,4 +11,7 @@ int procfs_tasks_get_current(uint64_t *ret); int procfs_cpu_get_usage(nsec_t *ret); -int procfs_memory_get_current(uint64_t *ret); +int procfs_memory_get(uint64_t *ret_total, uint64_t *ret_used); +static inline int procfs_memory_get_used(uint64_t *ret) { + return procfs_memory_get(NULL, ret); +} diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c index 30c228a78a..61180819b1 100644 --- a/src/basic/siphash24.c +++ b/src/basic/siphash24.c @@ -23,13 +23,13 @@ #include "siphash24.h" #include "unaligned.h" -static inline uint64_t rotate_left(uint64_t x, uint8_t b) { +static uint64_t rotate_left(uint64_t x, uint8_t b) { assert(b < 64); return (x << b) | (x >> (64 - b)); } -static inline void sipround(struct siphash *state) { +static void sipround(struct siphash *state) { assert(state); state->v0 += state->v1; @@ -48,7 +48,7 @@ static inline void sipround(struct siphash *state) { state->v2 = rotate_left(state->v2, 32); } -void siphash24_init(struct siphash *state, const uint8_t k[16]) { +void siphash24_init(struct siphash *state, const uint8_t k[static 16]) { uint64_t k0, k1; assert(state); @@ -187,7 +187,7 @@ uint64_t siphash24_finalize(struct siphash *state) { return state->v0 ^ state->v1 ^ state->v2 ^ state->v3; } -uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) { +uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]) { struct siphash state; assert(in); diff --git a/src/basic/siphash24.h b/src/basic/siphash24.h index 70a4a03f6a..67c4f7560c 100644 --- a/src/basic/siphash24.h +++ b/src/basic/siphash24.h @@ -15,14 +15,14 @@ struct siphash { size_t inlen; }; -void siphash24_init(struct siphash *state, const uint8_t k[16]); +void siphash24_init(struct siphash *state, const uint8_t k[static 16]); void siphash24_compress(const void *in, size_t inlen, struct siphash *state); #define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state)) uint64_t siphash24_finalize(struct siphash *state); -uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]); +uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]); -static inline uint64_t siphash24_string(const char *s, const uint8_t k[16]) { +static inline uint64_t siphash24_string(const char *s, const uint8_t k[static 16]) { return siphash24(s, strlen(s) + 1, k); } diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 57700e2388..ea2bbc368b 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -67,13 +67,22 @@ int is_device_node(const char *path) { return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode)); } -int dir_is_empty(const char *path) { - _cleanup_closedir_ DIR *d; +int dir_is_empty_at(int dir_fd, const char *path) { + _cleanup_close_ int fd = -1; + _cleanup_closedir_ DIR *d = NULL; struct dirent *de; - d = opendir(path); + if (path) + fd = openat(dir_fd, path, O_RDONLY|O_DIRECTORY|O_CLOEXEC); + else + fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (fd < 0) + return -errno; + + d = fdopendir(fd); if (!d) return -errno; + fd = -1; FOREACH_DIRENT(de, d, return -errno) return 0; @@ -338,7 +347,6 @@ int device_path_make_major_minor(mode_t mode, dev_t devno, char **ret) { return -ENOMEM; return 0; - } int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) { diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index 0a08e642b5..74fb7251b3 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -15,7 +15,10 @@ int is_dir(const char *path, bool follow); int is_dir_fd(int fd); int is_device_node(const char *path); -int dir_is_empty(const char *path); +int dir_is_empty_at(int dir_fd, const char *path); +static inline int dir_is_empty(const char *path) { + return dir_is_empty_at(AT_FDCWD, path); +} static inline int dir_is_populated(const char *path) { int r; diff --git a/src/basic/string-util.c b/src/basic/string-util.c index 05469ac01f..93917bc0f0 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -742,7 +742,7 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin return ret; } -static void advance_offsets(ssize_t diff, size_t offsets[2], size_t shift[2], size_t size) { +static void advance_offsets(ssize_t diff, size_t offsets[static 2], size_t shift[static 2], size_t size) { if (!offsets) return; diff --git a/src/basic/string-util.h b/src/basic/string-util.h index a5b5a16a5d..38070abb22 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -6,6 +6,7 @@ #include <stddef.h> #include <string.h> +#include "alloc-util.h" #include "macro.h" /* What is interpreted as whitespace? */ @@ -111,7 +112,7 @@ char *strjoin_real(const char *x, ...) _sentinel_; size_t _i_; \ for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ _len_ += strlen(_appendees_[_i_]); \ - _p_ = _d_ = alloca(_len_ + 1); \ + _p_ = _d_ = newa(char, _len_ + 1); \ for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ _p_ = stpcpy(_p_, _appendees_[_i_]); \ *_p_ = 0; \ diff --git a/src/basic/strv.h b/src/basic/strv.h index aa4cd4aaca..392cab65be 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -156,17 +156,10 @@ void strv_print(char **l); _found; \ }) -#define FOREACH_STRING(x, ...) \ - for (char **_l = ({ \ - char **_ll = STRV_MAKE(__VA_ARGS__); \ - x = _ll ? _ll[0] : NULL; \ - _ll; \ - }); \ - _l && *_l; \ - x = ({ \ - _l ++; \ - _l[0]; \ - })) +#define FOREACH_STRING(x, y, ...) \ + for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \ + x; \ + x = *(++_l)) char **strv_reverse(char **l); char **strv_shell_escape(char **l, const char *bad); diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 557c75debc..62cdc305f9 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -24,7 +24,6 @@ #include "parse-util.h" #include "path-util.h" #include "process-util.h" -#include "serialize.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" diff --git a/src/basic/tmpfile-util.c b/src/basic/tmpfile-util.c index 669eb2666c..bc92d6a6de 100644 --- a/src/basic/tmpfile-util.c +++ b/src/basic/tmpfile-util.c @@ -8,6 +8,7 @@ #include "hexdecoct.h" #include "macro.h" #include "memfd-util.h" +#include "missing_fcntl.h" #include "missing_syscall.h" #include "path-util.h" #include "process-util.h" diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h index d373f03aca..0629db3f67 100644 --- a/src/basic/unit-name.h +++ b/src/basic/unit-name.h @@ -9,9 +9,9 @@ #define UNIT_NAME_MAX 256 typedef enum UnitNameFlags { - UNIT_NAME_PLAIN = 1, /* Allow foo.service */ - UNIT_NAME_INSTANCE = 2, /* Allow foo@bar.service */ - UNIT_NAME_TEMPLATE = 4, /* Allow foo@.service */ + UNIT_NAME_PLAIN = 1 << 0, /* Allow foo.service */ + UNIT_NAME_INSTANCE = 1 << 1, /* Allow foo@bar.service */ + UNIT_NAME_TEMPLATE = 1 << 2, /* Allow foo@.service */ UNIT_NAME_ANY = UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE, } UnitNameFlags; @@ -50,8 +50,8 @@ int unit_name_from_path_instance(const char *prefix, const char *path, const cha int unit_name_to_path(const char *name, char **ret); typedef enum UnitNameMangle { - UNIT_NAME_MANGLE_GLOB = 1, - UNIT_NAME_MANGLE_WARN = 2, + UNIT_NAME_MANGLE_GLOB = 1 << 0, + UNIT_NAME_MANGLE_WARN = 1 << 1, } UnitNameMangle; int unit_name_mangle_with_suffix(const char *name, UnitNameMangle flags, const char *suffix, char **ret); diff --git a/src/basic/user-util.c b/src/basic/user-util.c index d410c9068b..260f3d2057 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -87,7 +87,7 @@ char *getusername_malloc(void) { return uid_to_name(getuid()); } -static inline bool is_nologin_shell(const char *shell) { +static bool is_nologin_shell(const char *shell) { return PATH_IN_SET(shell, /* 'nologin' is the friendliest way to disable logins for a user account. It prints a nice @@ -733,10 +733,6 @@ int maybe_setgroups(size_t size, const gid_t *list) { } bool synthesize_nobody(void) { - -#ifdef NOLEGACY - return true; -#else /* Returns true when we shall synthesize the "nobody" user (which we do by default). This can be turned off by * touching /etc/systemd/dont-synthesize-nobody in order to provide upgrade compatibility with legacy systems * that used the "nobody" user name and group name for other UIDs/GIDs than 65534. @@ -750,7 +746,6 @@ bool synthesize_nobody(void) { cache = access("/etc/systemd/dont-synthesize-nobody", F_OK) < 0; return cache; -#endif } int putpwent_sane(const struct passwd *pw, FILE *stream) { diff --git a/src/basic/util.c b/src/basic/util.c index c4f12a6daa..e577c93e60 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -557,7 +557,7 @@ uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) { } int version(void) { - puts(PACKAGE_STRING "\n" + puts("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n" SYSTEMD_FEATURES); return 0; } diff --git a/src/basic/util.h b/src/basic/util.h index f009d37d4c..dc33d66067 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -174,12 +174,21 @@ static inline void *mempset(void *s, int c, size_t n) { } static inline void _reset_errno_(int *saved_errno) { + if (*saved_errno < 0) /* Invalidated by UNPROTECT_ERRNO? */ + return; + errno = *saved_errno; } #define PROTECT_ERRNO \ _cleanup_(_reset_errno_) _unused_ int _saved_errno_ = errno +#define UNPROTECT_ERRNO \ + do { \ + errno = _saved_errno_; \ + _saved_errno_ = -1; \ + } while (false) + 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();" |