summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/alloc-util.h49
-rw-r--r--src/basic/btrfs-util.c2
-rw-r--r--src/basic/btrfs-util.h16
-rw-r--r--src/basic/build.h2
-rw-r--r--src/basic/capability-util.c1
-rw-r--r--src/basic/cgroup-util.c12
-rw-r--r--src/basic/cgroup-util.h12
-rw-r--r--src/basic/copy.c28
-rw-r--r--src/basic/copy.h9
-rw-r--r--src/basic/env-file.c32
-rw-r--r--src/basic/env-util.c2
-rw-r--r--src/basic/env-util.h6
-rw-r--r--src/basic/extract-word.h12
-rw-r--r--src/basic/fd-util.c39
-rw-r--r--src/basic/fd-util.h2
-rw-r--r--src/basic/hashmap.c10
-rw-r--r--src/basic/hashmap.h1
-rw-r--r--src/basic/in-addr-util.c37
-rw-r--r--src/basic/in-addr-util.h22
-rw-r--r--src/basic/io-util.c10
-rw-r--r--src/basic/io-util.h2
-rw-r--r--src/basic/meson.build3
-rw-r--r--src/basic/missing_if_link.h3
-rw-r--r--src/basic/missing_syscall.h1
-rw-r--r--src/basic/path-util.h2
-rw-r--r--src/basic/prioq.c7
-rw-r--r--src/basic/prioq.h8
-rw-r--r--src/basic/process-util.c91
-rw-r--r--src/basic/process-util.h4
-rw-r--r--src/basic/procfs-util.c9
-rw-r--r--src/basic/procfs-util.h5
-rw-r--r--src/basic/siphash24.c8
-rw-r--r--src/basic/siphash24.h6
-rw-r--r--src/basic/stat-util.c16
-rw-r--r--src/basic/stat-util.h5
-rw-r--r--src/basic/string-util.c2
-rw-r--r--src/basic/string-util.h3
-rw-r--r--src/basic/strv.h15
-rw-r--r--src/basic/time-util.c1
-rw-r--r--src/basic/tmpfile-util.c1
-rw-r--r--src/basic/unit-name.h10
-rw-r--r--src/basic/user-util.c7
-rw-r--r--src/basic/util.c2
-rw-r--r--src/basic/util.h9
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();"