systemd: merge branch systemd into master

This commit is contained in:
Thomas Haller
2020-09-24 11:21:13 +02:00
48 changed files with 1333 additions and 806 deletions

View File

@@ -88,6 +88,8 @@ G_STMT_START { \
#define ENABLE_GSHADOW FALSE #define ENABLE_GSHADOW FALSE
#define HAVE_SECCOMP 0
/*****************************************************************************/ /*****************************************************************************/
/* systemd cannot be compiled with "-Wdeclaration-after-statement". In particular /* systemd cannot be compiled with "-Wdeclaration-after-statement". In particular

View File

@@ -211,17 +211,21 @@ static int parse_env_file_internal(
case DOUBLE_QUOTE_VALUE_ESCAPE: case DOUBLE_QUOTE_VALUE_ESCAPE:
state = DOUBLE_QUOTE_VALUE; state = DOUBLE_QUOTE_VALUE;
if (c == '"') { if (strchr(SHELL_NEED_ESCAPE, c)) {
/* If this is a char that needs escaping, just unescape it. */
if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
return -ENOMEM; return -ENOMEM;
value[n_value++] = '"'; value[n_value++] = c;
} else if (!strchr(NEWLINE, c)) { } else if (c != '\n') {
/* If other char than what needs escaping, keep the "\" in place, like the
* real shell does. */
if (!GREEDY_REALLOC(value, value_alloc, n_value+3)) if (!GREEDY_REALLOC(value, value_alloc, n_value+3))
return -ENOMEM; return -ENOMEM;
value[n_value++] = '\\'; value[n_value++] = '\\';
value[n_value++] = c; value[n_value++] = c;
} }
/* Escaped newlines (aka "continuation lines") are eaten up entirely */
break; break;
case COMMENT: case COMMENT:

View File

@@ -690,7 +690,7 @@ char **replace_env_argv(char **argv, char **env) {
if (e) { if (e) {
int r; int r;
r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE); r = strv_split_full(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE);
if (r < 0) { if (r < 0) {
ret[k] = NULL; ret[k] = NULL;
strv_free(ret); strv_free(ret);
@@ -744,7 +744,6 @@ int getenv_bool(const char *p) {
return parse_boolean(e); return parse_boolean(e);
} }
#if 0 /* NM_IGNORED */
int getenv_bool_secure(const char *p) { int getenv_bool_secure(const char *p) {
const char *e; const char *e;
@@ -754,4 +753,3 @@ int getenv_bool_secure(const char *p) {
return parse_boolean(e); return parse_boolean(e);
} }
#endif /* NM_IGNORED */

View File

@@ -77,7 +77,7 @@ int cescape_char(char c, char *buf) {
return buf - buf_old; return buf - buf_old;
} }
char *cescape_length(const char *s, size_t n) { char* cescape_length(const char *s, size_t n) {
const char *f; const char *f;
char *r, *t; char *r, *t;
@@ -98,7 +98,7 @@ char *cescape_length(const char *s, size_t n) {
return r; return r;
} }
char *cescape(const char *s) { char* cescape(const char *s) {
assert(s); assert(s);
return cescape_length(s, strlen(s)); return cescape_length(s, strlen(s));
@@ -363,7 +363,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
return t - r; return t - r;
} }
char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits) { char* xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits) {
char *ans, *t, *prev, *prev2; char *ans, *t, *prev, *prev2;
const char *f; const char *f;
@@ -430,7 +430,7 @@ char *xescape_full(const char *s, const char *bad, size_t console_width, bool ei
return ans; return ans;
} }
char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit) { char* escape_non_printable_full(const char *str, size_t console_width, bool eight_bit) {
if (eight_bit) if (eight_bit)
return xescape_full(str, "", console_width, true); return xescape_full(str, "", console_width, true);
else else
@@ -438,7 +438,7 @@ char *escape_non_printable_full(const char *str, size_t console_width, bool eigh
} }
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */
char *octescape(const char *s, size_t len) { char* octescape(const char *s, size_t len) {
char *r, *t; char *r, *t;
const char *f; const char *f;
@@ -466,7 +466,7 @@ char *octescape(const char *s, size_t len) {
} }
static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) { static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) {
assert(bad); assert(bad);
for (; *s; s++) { for (; *s; s++) {
@@ -485,7 +485,7 @@ static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, b
return t; return t;
} }
char *shell_escape(const char *s, const char *bad) { char* shell_escape(const char *s, const char *bad) {
char *r, *t; char *r, *t;
r = new(char, strlen(s)*2+1); r = new(char, strlen(s)*2+1);

View File

@@ -43,8 +43,8 @@ typedef enum EscapeStyle {
* syntax (a string enclosed in $'') instead of plain quotes. */ * syntax (a string enclosed in $'') instead of plain quotes. */
} EscapeStyle; } EscapeStyle;
char *cescape(const char *s); char* cescape(const char *s);
char *cescape_length(const char *s, size_t n); char* cescape_length(const char *s, size_t n);
int cescape_char(char c, char *buf); int cescape_char(char c, char *buf);
int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret); int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret);
@@ -56,12 +56,12 @@ static inline int cunescape(const char *s, UnescapeFlags flags, char **ret) {
} }
int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit, bool accept_nul); int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit, bool accept_nul);
char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits); char* xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits);
static inline char *xescape(const char *s, const char *bad) { static inline char* xescape(const char *s, const char *bad) {
return xescape_full(s, bad, SIZE_MAX, false); return xescape_full(s, bad, SIZE_MAX, false);
} }
char *octescape(const char *s, size_t len); char* octescape(const char *s, size_t len);
char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit); char* escape_non_printable_full(const char *str, size_t console_width, bool eight_bit);
char *shell_escape(const char *s, const char *bad); char* shell_escape(const char *s, const char *bad);
char* shell_maybe_quote(const char *s, EscapeStyle style); char* shell_maybe_quote(const char *s, EscapeStyle style);

View File

@@ -16,6 +16,7 @@
#include "log.h" #include "log.h"
#include "macro.h" #include "macro.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h"
#include "utf8.h" #include "utf8.h"
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) { int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {

View File

@@ -379,6 +379,7 @@ bool fdname_is_valid(const char *s) {
return p - s < 256; return p - s < 256;
} }
#if 0 /* NM_IGNORED */
int fd_get_path(int fd, char **ret) { int fd_get_path(int fd, char **ret) {
char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
int r; int r;
@@ -389,18 +390,15 @@ int fd_get_path(int fd, char **ret) {
/* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make /* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make
* things debuggable and distinguish the two. */ * things debuggable and distinguish the two. */
if (access("/proc/self/fd/", F_OK) < 0) if (proc_mounted() == 0)
/* /proc is not available or not set up properly, we're most likely in some chroot return -ENOSYS; /* /proc is not available or not set up properly, we're most likely in some chroot
* environment. */ * environment. */
return errno == ENOENT ? -EOPNOTSUPP : -errno;
return -EBADF; /* The directory exists, hence it's the fd that doesn't. */ return -EBADF; /* The directory exists, hence it's the fd that doesn't. */
} }
return r; return r;
} }
#if 0 /* NM_IGNORED */
int move_fd(int from, int to, int cloexec) { int move_fd(int from, int to, int cloexec) {
int r; int r;
@@ -736,8 +734,7 @@ int fd_duplicate_data_fd(int fd) {
if (f != 0) if (f != 0)
return -errno; return -errno;
safe_close(copy_fd); CLOSE_AND_REPLACE(copy_fd, tmp_fd);
copy_fd = TAKE_FD(tmp_fd);
remains = mfree(remains); remains = mfree(remains);
remains_size = 0; remains_size = 0;
@@ -872,8 +869,7 @@ int rearrange_stdio(int original_input_fd, int original_output_fd, int original_
goto finish; goto finish;
} }
safe_close(null_fd); CLOSE_AND_REPLACE(null_fd, copy);
null_fd = copy;
} }
} }
@@ -983,7 +979,7 @@ int read_nr_open(void) {
return v; return v;
} }
/* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */ /* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */
return 1024 * 1024; return 1024 * 1024;
} }
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -93,6 +93,16 @@ static inline int make_null_stdio(void) {
_fd_; \ _fd_; \
}) })
/* Like free_and_replace(), but for file descriptors */
#define CLOSE_AND_REPLACE(a, b) \
({ \
int *_fdp_ = &(a); \
safe_close(*_fdp_); \
*_fdp_ = TAKE_FD(b); \
0; \
})
int fd_reopen(int fd, int flags); int fd_reopen(int fd, int flags);
int read_nr_open(void); int read_nr_open(void);

View File

@@ -123,7 +123,7 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
if (!IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM)) /* FAT returns EPERM on link()… */ if (!IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM)) /* FAT returns EPERM on link()… */
return -errno; return -errno;
/* OK, neither RENAME_NOREPLACE nor linkat()+unlinkat() worked. Let's then fallback to the racy TOCTOU /* OK, neither RENAME_NOREPLACE nor linkat()+unlinkat() worked. Let's then fall back to the racy TOCTOU
* vulnerable accessat(F_OK) check followed by classic, replacing renameat(), we have nothing better. */ * vulnerable accessat(F_OK) check followed by classic, replacing renameat(), we have nothing better. */
if (faccessat(newdirfd, newpath, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) if (faccessat(newdirfd, newpath, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
@@ -234,6 +234,7 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
bool do_chown, do_chmod; bool do_chown, do_chmod;
struct stat st; struct stat st;
int r;
/* Change ownership and access mode of the specified fd. Tries to do so safely, ensuring that at no /* Change ownership and access mode of the specified fd. Tries to do so safely, ensuring that at no
* point in time the access mode is above the old access mode under the old ownership or the new * point in time the access mode is above the old access mode under the old ownership or the new
@@ -264,65 +265,23 @@ int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
if (do_chown && do_chmod) { if (do_chown && do_chmod) {
mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */ mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */
if (((minimal ^ st.st_mode) & 07777) != 0) if (((minimal ^ st.st_mode) & 07777) != 0) {
if (fchmod_opath(fd, minimal & 07777) < 0) r = fchmod_opath(fd, minimal & 07777);
return -errno; if (r < 0)
return r;
}
} }
if (do_chown) if (do_chown)
if (fchownat(fd, "", uid, gid, AT_EMPTY_PATH) < 0) if (fchownat(fd, "", uid, gid, AT_EMPTY_PATH) < 0)
return -errno; return -errno;
if (do_chmod) if (do_chmod) {
if (fchmod_opath(fd, mode & 07777) < 0) r = fchmod_opath(fd, mode & 07777);
return -errno; if (r < 0)
return r;
return do_chown || do_chmod;
}
int chmod_and_chown_unsafe(const char *path, mode_t mode, uid_t uid, gid_t gid) {
bool do_chown, do_chmod;
struct stat st;
assert(path);
/* Change ownership and access mode of the specified path, see description of fchmod_and_chown().
* Should only be used on trusted paths. */
if (lstat(path, &st) < 0)
return -errno;
do_chown =
(uid != UID_INVALID && st.st_uid != uid) ||
(gid != GID_INVALID && st.st_gid != gid);
do_chmod =
!S_ISLNK(st.st_mode) && /* chmod is not defined on symlinks */
((mode != MODE_INVALID && ((st.st_mode ^ mode) & 07777) != 0) ||
do_chown); /* If we change ownership, make sure we reset the mode afterwards, since chown()
* modifies the access mode too */
if (mode == MODE_INVALID)
mode = st.st_mode; /* If we only shall do a chown(), save original mode, since chown() might break it. */
else if ((mode & S_IFMT) != 0 && ((mode ^ st.st_mode) & S_IFMT) != 0)
return -EINVAL; /* insist on the right file type if it was specified */
if (do_chown && do_chmod) {
mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */
if (((minimal ^ st.st_mode) & 07777) != 0)
if (chmod(path, minimal & 07777) < 0)
return -errno;
} }
if (do_chown)
if (lchown(path, uid, gid) < 0)
return -errno;
if (do_chmod)
if (chmod(path, mode & 07777) < 0)
return -errno;
return do_chown || do_chmod; return do_chown || do_chmod;
} }
@@ -771,7 +730,7 @@ static int log_unsafe_transition(int a, int b, const char *path, unsigned flags)
return log_warning_errno(SYNTHETIC_ERRNO(ENOLINK), return log_warning_errno(SYNTHETIC_ERRNO(ENOLINK),
"Detected unsafe path transition %s %s %s during canonicalization of %s.", "Detected unsafe path transition %s %s %s during canonicalization of %s.",
n1, special_glyph(SPECIAL_GLYPH_ARROW), n2, path); strna(n1), special_glyph(SPECIAL_GLYPH_ARROW), strna(n2), path);
} }
static int log_autofs_mount_point(int fd, const char *path, unsigned flags) { static int log_autofs_mount_point(int fd, const char *path, unsigned flags) {
@@ -784,7 +743,7 @@ static int log_autofs_mount_point(int fd, const char *path, unsigned flags) {
return log_warning_errno(SYNTHETIC_ERRNO(EREMOTE), return log_warning_errno(SYNTHETIC_ERRNO(EREMOTE),
"Detected autofs mount point %s during canonicalization of %s.", "Detected autofs mount point %s during canonicalization of %s.",
n1, path); strna(n1), path);
} }
int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) { int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) {
@@ -1304,16 +1263,25 @@ int chase_symlinks_and_stat(
int access_fd(int fd, int mode) { int access_fd(int fd, int mode) {
char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
int r;
/* Like access() but operates on an already open fd */ /* Like access() but operates on an already open fd */
xsprintf(p, "/proc/self/fd/%i", fd); xsprintf(p, "/proc/self/fd/%i", fd);
r = access(p, mode); if (access(p, mode) < 0) {
if (r < 0) if (errno != ENOENT)
return -errno; return -errno;
return r; /* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's
* make things debuggable and distinguish the two. */
if (proc_mounted() == 0)
return -ENOSYS; /* /proc is not available or not set up properly, we're most likely in some chroot
* environment. */
return -EBADF; /* The directory exists, hence it's the fd that doesn't. */
}
return 0;
} }
void unlink_tempfilep(char (*p)[]) { void unlink_tempfilep(char (*p)[]) {
@@ -1434,6 +1402,7 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
return 0; return 0;
} }
#if 0 /* NM_IGNORED */
int fsync_directory_of_file(int fd) { int fsync_directory_of_file(int fd) {
_cleanup_free_ char *path = NULL; _cleanup_free_ char *path = NULL;
_cleanup_close_ int dfd = -1; _cleanup_close_ int dfd = -1;
@@ -1447,9 +1416,9 @@ int fsync_directory_of_file(int fd) {
if (r < 0) { if (r < 0) {
log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m", log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m",
fd, fd,
r == -EOPNOTSUPP ? ", ignoring" : ""); r == -ENOSYS ? ", ignoring" : "");
if (r == -EOPNOTSUPP) if (r == -ENOSYS)
/* If /proc is not available, we're most likely running in some /* If /proc is not available, we're most likely running in some
* chroot environment, and syncing the directory is not very * chroot environment, and syncing the directory is not very
* important in that case. Let's just silently do nothing. */ * important in that case. Let's just silently do nothing. */
@@ -1470,6 +1439,7 @@ int fsync_directory_of_file(int fd) {
return 0; return 0;
} }
#endif /* NM_IGNORED */
int fsync_full(int fd) { int fsync_full(int fd) {
int r, q; int r, q;

View File

@@ -34,7 +34,6 @@ int readlink_and_make_absolute(const char *p, char **r);
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid); int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid);
int chmod_and_chown_unsafe(const char *path, mode_t mode, uid_t uid, gid_t gid);
int fchmod_umask(int fd, mode_t mode); int fchmod_umask(int fd, mode_t mode);
int fchmod_opath(int fd, mode_t m); int fchmod_opath(int fd, mode_t m);

View File

@@ -3,6 +3,7 @@
#include "nm-sd-adapt-shared.h" #include "nm-sd-adapt-shared.h"
#include <errno.h> #include <errno.h>
#include <pthread.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@@ -21,7 +22,6 @@
#include "strv.h" #include "strv.h"
#if ENABLE_DEBUG_HASHMAP #if ENABLE_DEBUG_HASHMAP
#include <pthread.h>
#include "list.h" #include "list.h"
#endif #endif
@@ -191,7 +191,6 @@ assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3));
* a handful of directly stored entries in a hashmap. When a hashmap * a handful of directly stored entries in a hashmap. When a hashmap
* outgrows direct storage, it gets its own key for indirect storage. */ * outgrows direct storage, it gets its own key for indirect storage. */
static uint8_t shared_hash_key[HASH_KEY_SIZE]; static uint8_t shared_hash_key[HASH_KEY_SIZE];
static bool shared_hash_key_initialized;
/* Fields that all hashmap/set types must have */ /* Fields that all hashmap/set types must have */
struct HashmapBase { struct HashmapBase {
@@ -325,12 +324,12 @@ static void n_entries_dec(HashmapBase *h) {
h->n_direct_entries--; h->n_direct_entries--;
} }
static void *storage_ptr(HashmapBase *h) { static void* storage_ptr(HashmapBase *h) {
return h->has_indirect ? h->indirect.storage return h->has_indirect ? h->indirect.storage
: h->direct.storage; : h->direct.storage;
} }
static uint8_t *hash_key(HashmapBase *h) { static uint8_t* hash_key(HashmapBase *h) {
return h->has_indirect ? h->indirect.hash_key return h->has_indirect ? h->indirect.hash_key
: shared_hash_key; : shared_hash_key;
} }
@@ -373,16 +372,16 @@ static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) {
memcpy(hash_key, current, sizeof(current)); memcpy(hash_key, current, sizeof(current));
} }
static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) { static struct hashmap_base_entry* bucket_at(HashmapBase *h, unsigned idx) {
return (struct hashmap_base_entry*) return (struct hashmap_base_entry*)
((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size);
} }
static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) { static struct plain_hashmap_entry* plain_bucket_at(Hashmap *h, unsigned idx) {
return (struct plain_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx); return (struct plain_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx);
} }
static struct ordered_hashmap_entry *ordered_bucket_at(OrderedHashmap *h, unsigned idx) { static struct ordered_hashmap_entry* ordered_bucket_at(OrderedHashmap *h, unsigned idx) {
return (struct ordered_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx); return (struct ordered_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx);
} }
@@ -390,13 +389,13 @@ static struct set_entry *set_bucket_at(Set *h, unsigned idx) {
return (struct set_entry*) bucket_at(HASHMAP_BASE(h), idx); return (struct set_entry*) bucket_at(HASHMAP_BASE(h), idx);
} }
static struct ordered_hashmap_entry *bucket_at_swap(struct swap_entries *swap, unsigned idx) { static struct ordered_hashmap_entry* bucket_at_swap(struct swap_entries *swap, unsigned idx) {
return &swap->e[idx - _IDX_SWAP_BEGIN]; return &swap->e[idx - _IDX_SWAP_BEGIN];
} }
/* Returns a pointer to the bucket at index idx. /* Returns a pointer to the bucket at index idx.
* Understands real indexes and swap indexes, hence "_virtual". */ * Understands real indexes and swap indexes, hence "_virtual". */
static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_entries *swap, static struct hashmap_base_entry* bucket_at_virtual(HashmapBase *h, struct swap_entries *swap,
unsigned idx) { unsigned idx) {
if (idx < _IDX_SWAP_BEGIN) if (idx < _IDX_SWAP_BEGIN)
return bucket_at(h, idx); return bucket_at(h, idx);
@@ -407,7 +406,7 @@ static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_
assert_not_reached("Invalid index"); assert_not_reached("Invalid index");
} }
static dib_raw_t *dib_raw_ptr(HashmapBase *h) { static dib_raw_t* dib_raw_ptr(HashmapBase *h) {
return (dib_raw_t*) return (dib_raw_t*)
((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h)); ((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h));
} }
@@ -505,7 +504,7 @@ static unsigned prev_idx(HashmapBase *h, unsigned idx) {
return (n_buckets(h) + idx - 1U) % n_buckets(h); return (n_buckets(h) + idx - 1U) % n_buckets(h);
} }
static void *entry_value(HashmapBase *h, struct hashmap_base_entry *e) { static void* entry_value(HashmapBase *h, struct hashmap_base_entry *e) {
switch (h->type) { switch (h->type) {
case HASHMAP_TYPE_PLAIN: case HASHMAP_TYPE_PLAIN:
@@ -732,16 +731,12 @@ bool _hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **ke
return true; return true;
} }
bool set_iterate(const Set *s, Iterator *i, void **value) {
return _hashmap_iterate(HASHMAP_BASE((Set*) s), i, value, NULL);
}
#define HASHMAP_FOREACH_IDX(idx, h, i) \ #define HASHMAP_FOREACH_IDX(idx, h, i) \
for ((i) = ITERATOR_FIRST, (idx) = hashmap_iterate_entry((h), &(i)); \ for ((i) = ITERATOR_FIRST, (idx) = hashmap_iterate_entry((h), &(i)); \
(idx != IDX_NIL); \ (idx != IDX_NIL); \
(idx) = hashmap_iterate_entry((h), &(i))) (idx) = hashmap_iterate_entry((h), &(i)))
IteratedCache *_hashmap_iterated_cache_new(HashmapBase *h) { IteratedCache* _hashmap_iterated_cache_new(HashmapBase *h) {
IteratedCache *cache; IteratedCache *cache;
assert(h); assert(h);
@@ -770,7 +765,11 @@ static void reset_direct_storage(HashmapBase *h) {
memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets); memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
} }
static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { static void shared_hash_key_initialize(void) {
random_bytes(shared_hash_key, sizeof(shared_hash_key));
}
static struct HashmapBase* hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
HashmapBase *h; HashmapBase *h;
const struct hashmap_type_info *hi = &hashmap_type_info[type]; const struct hashmap_type_info *hi = &hashmap_type_info[type];
bool up; bool up;
@@ -792,10 +791,8 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu
reset_direct_storage(h); reset_direct_storage(h);
if (!shared_hash_key_initialized) { static pthread_once_t once = PTHREAD_ONCE_INIT;
random_bytes(shared_hash_key, sizeof(shared_hash_key)); assert_se(pthread_once(&once, shared_hash_key_initialize) == 0);
shared_hash_key_initialized= true;
}
#if ENABLE_DEBUG_HASHMAP #if ENABLE_DEBUG_HASHMAP
h->debug.func = func; h->debug.func = func;
@@ -850,6 +847,16 @@ int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBU
return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS); return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
} }
int _ordered_hashmap_ensure_put(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS) {
int r;
r = _ordered_hashmap_ensure_allocated(h, hash_ops HASHMAP_DEBUG_PASS_ARGS);
if (r < 0)
return r;
return ordered_hashmap_put(*h, key, value);
}
static void hashmap_free_no_clear(HashmapBase *h) { static void hashmap_free_no_clear(HashmapBase *h) {
assert(!h->has_indirect); assert(!h->has_indirect);
assert(h->n_direct_entries == 0); assert(h->n_direct_entries == 0);
@@ -868,7 +875,7 @@ static void hashmap_free_no_clear(HashmapBase *h) {
free(h); free(h);
} }
HashmapBase *_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) { HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) {
if (h) { if (h) {
_hashmap_clear(h, default_free_key, default_free_value); _hashmap_clear(h, default_free_key, default_free_value);
hashmap_free_no_clear(h); hashmap_free_no_clear(h);
@@ -1325,7 +1332,7 @@ int hashmap_update(Hashmap *h, const void *key, void *value) {
return 0; return 0;
} }
void *_hashmap_get(HashmapBase *h, const void *key) { void* _hashmap_get(HashmapBase *h, const void *key) {
struct hashmap_base_entry *e; struct hashmap_base_entry *e;
unsigned hash, idx; unsigned hash, idx;
@@ -1341,7 +1348,7 @@ void *_hashmap_get(HashmapBase *h, const void *key) {
return entry_value(h, e); return entry_value(h, e);
} }
void *hashmap_get2(Hashmap *h, const void *key, void **key2) { void* hashmap_get2(Hashmap *h, const void *key, void **key2) {
struct plain_hashmap_entry *e; struct plain_hashmap_entry *e;
unsigned hash, idx; unsigned hash, idx;
@@ -1370,7 +1377,7 @@ bool _hashmap_contains(HashmapBase *h, const void *key) {
return bucket_scan(h, hash, key) != IDX_NIL; return bucket_scan(h, hash, key) != IDX_NIL;
} }
void *_hashmap_remove(HashmapBase *h, const void *key) { void* _hashmap_remove(HashmapBase *h, const void *key) {
struct hashmap_base_entry *e; struct hashmap_base_entry *e;
unsigned hash, idx; unsigned hash, idx;
void *data; void *data;
@@ -1390,7 +1397,7 @@ void *_hashmap_remove(HashmapBase *h, const void *key) {
return data; return data;
} }
void *hashmap_remove2(Hashmap *h, const void *key, void **rkey) { void* hashmap_remove2(Hashmap *h, const void *key, void **rkey) {
struct plain_hashmap_entry *e; struct plain_hashmap_entry *e;
unsigned hash, idx; unsigned hash, idx;
void *data; void *data;
@@ -1508,7 +1515,7 @@ int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_
return 0; return 0;
} }
void *_hashmap_remove_value(HashmapBase *h, const void *key, void *value) { void* _hashmap_remove_value(HashmapBase *h, const void *key, void *value) {
struct hashmap_base_entry *e; struct hashmap_base_entry *e;
unsigned hash, idx; unsigned hash, idx;
@@ -1538,7 +1545,7 @@ static unsigned find_first_entry(HashmapBase *h) {
return hashmap_iterate_entry(h, &i); return hashmap_iterate_entry(h, &i);
} }
void *_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) { void* _hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) {
struct hashmap_base_entry *e; struct hashmap_base_entry *e;
void *key, *data; void *key, *data;
unsigned idx; unsigned idx;
@@ -1713,7 +1720,7 @@ int _hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) {
return 0; return 0;
} }
HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) { HashmapBase* _hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) {
HashmapBase *copy; HashmapBase *copy;
int r; int r;
@@ -1741,7 +1748,7 @@ HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) {
return copy; return copy;
} }
char **_hashmap_get_strv(HashmapBase *h) { char** _hashmap_get_strv(HashmapBase *h) {
char **sv; char **sv;
Iterator i; Iterator i;
unsigned idx, n; unsigned idx, n;
@@ -1758,7 +1765,7 @@ char **_hashmap_get_strv(HashmapBase *h) {
return sv; return sv;
} }
void *ordered_hashmap_next(OrderedHashmap *h, const void *key) { void* ordered_hashmap_next(OrderedHashmap *h, const void *key) {
struct ordered_hashmap_entry *e; struct ordered_hashmap_entry *e;
unsigned hash, idx; unsigned hash, idx;
@@ -1965,7 +1972,7 @@ int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void
return 0; return 0;
} }
IteratedCache *iterated_cache_free(IteratedCache *cache) { IteratedCache* iterated_cache_free(IteratedCache *cache) {
if (cache) { if (cache) {
free(cache->keys.ptr); free(cache->keys.ptr);
free(cache->values.ptr); free(cache->values.ptr);

View File

@@ -83,8 +83,8 @@ typedef struct {
# define HASHMAP_DEBUG_PASS_ARGS # define HASHMAP_DEBUG_PASS_ARGS
#endif #endif
Hashmap *_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); Hashmap* _hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
OrderedHashmap *_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); OrderedHashmap* _ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
#define hashmap_new(ops) _hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) #define hashmap_new(ops) _hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
#define ordered_hashmap_new(ops) _ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) #define ordered_hashmap_new(ops) _ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
@@ -96,39 +96,39 @@ OrderedHashmap *_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DE
0; \ 0; \
}) })
HashmapBase *_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value); HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
static inline Hashmap *hashmap_free(Hashmap *h) { static inline Hashmap* hashmap_free(Hashmap *h) {
return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL); return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL);
} }
static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) { static inline OrderedHashmap* ordered_hashmap_free(OrderedHashmap *h) {
return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL); return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL);
} }
static inline Hashmap *hashmap_free_free(Hashmap *h) { static inline Hashmap* hashmap_free_free(Hashmap *h) {
return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, free); return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, free);
} }
static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) { static inline OrderedHashmap* ordered_hashmap_free_free(OrderedHashmap *h) {
return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, free); return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, free);
} }
static inline Hashmap *hashmap_free_free_key(Hashmap *h) { static inline Hashmap* hashmap_free_free_key(Hashmap *h) {
return (void*) _hashmap_free(HASHMAP_BASE(h), free, NULL); return (void*) _hashmap_free(HASHMAP_BASE(h), free, NULL);
} }
static inline OrderedHashmap *ordered_hashmap_free_free_key(OrderedHashmap *h) { static inline OrderedHashmap* ordered_hashmap_free_free_key(OrderedHashmap *h) {
return (void*) _hashmap_free(HASHMAP_BASE(h), free, NULL); return (void*) _hashmap_free(HASHMAP_BASE(h), free, NULL);
} }
static inline Hashmap *hashmap_free_free_free(Hashmap *h) { static inline Hashmap* hashmap_free_free_free(Hashmap *h) {
return (void*) _hashmap_free(HASHMAP_BASE(h), free, free); return (void*) _hashmap_free(HASHMAP_BASE(h), free, free);
} }
static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) { static inline OrderedHashmap* ordered_hashmap_free_free_free(OrderedHashmap *h) {
return (void*) _hashmap_free(HASHMAP_BASE(h), free, free); return (void*) _hashmap_free(HASHMAP_BASE(h), free, free);
} }
IteratedCache *iterated_cache_free(IteratedCache *cache); IteratedCache* iterated_cache_free(IteratedCache *cache);
int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries); int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries);
HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS); HashmapBase* _hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS);
#define hashmap_copy(h) ((Hashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS)) #define hashmap_copy(h) ((Hashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS))
#define ordered_hashmap_copy(h) ((OrderedHashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS)) #define ordered_hashmap_copy(h) ((OrderedHashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS))
@@ -137,11 +137,14 @@ int _ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops
#define hashmap_ensure_allocated(h, ops) _hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) #define hashmap_ensure_allocated(h, ops) _hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
#define ordered_hashmap_ensure_allocated(h, ops) _ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) #define ordered_hashmap_ensure_allocated(h, ops) _ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
IteratedCache *_hashmap_iterated_cache_new(HashmapBase *h); int _ordered_hashmap_ensure_put(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS);
static inline IteratedCache *hashmap_iterated_cache_new(Hashmap *h) { #define ordered_hashmap_ensure_put(s, ops, key, value) _ordered_hashmap_ensure_put(s, ops, key, value HASHMAP_DEBUG_SRC_ARGS)
IteratedCache* _hashmap_iterated_cache_new(HashmapBase *h);
static inline IteratedCache* hashmap_iterated_cache_new(Hashmap *h) {
return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h)); return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h));
} }
static inline IteratedCache *ordered_hashmap_iterated_cache_new(OrderedHashmap *h) { static inline IteratedCache* ordered_hashmap_iterated_cache_new(OrderedHashmap *h) {
return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h)); return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h));
} }
@@ -163,7 +166,7 @@ static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, vo
return hashmap_replace(PLAIN_HASHMAP(h), key, value); return hashmap_replace(PLAIN_HASHMAP(h), key, value);
} }
void *_hashmap_get(HashmapBase *h, const void *key); void* _hashmap_get(HashmapBase *h, const void *key);
static inline void *hashmap_get(Hashmap *h, const void *key) { static inline void *hashmap_get(Hashmap *h, const void *key) {
return _hashmap_get(HASHMAP_BASE(h), key); return _hashmap_get(HASHMAP_BASE(h), key);
} }
@@ -171,7 +174,7 @@ static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) {
return _hashmap_get(HASHMAP_BASE(h), key); return _hashmap_get(HASHMAP_BASE(h), key);
} }
void *hashmap_get2(Hashmap *h, const void *key, void **rkey); void* hashmap_get2(Hashmap *h, const void *key, void **rkey);
static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) { static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) {
return hashmap_get2(PLAIN_HASHMAP(h), key, rkey); return hashmap_get2(PLAIN_HASHMAP(h), key, rkey);
} }
@@ -184,7 +187,7 @@ static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key)
return _hashmap_contains(HASHMAP_BASE(h), key); return _hashmap_contains(HASHMAP_BASE(h), key);
} }
void *_hashmap_remove(HashmapBase *h, const void *key); void* _hashmap_remove(HashmapBase *h, const void *key);
static inline void *hashmap_remove(Hashmap *h, const void *key) { static inline void *hashmap_remove(Hashmap *h, const void *key) {
return _hashmap_remove(HASHMAP_BASE(h), key); return _hashmap_remove(HASHMAP_BASE(h), key);
} }
@@ -192,17 +195,17 @@ static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) {
return _hashmap_remove(HASHMAP_BASE(h), key); return _hashmap_remove(HASHMAP_BASE(h), key);
} }
void *hashmap_remove2(Hashmap *h, const void *key, void **rkey); void* hashmap_remove2(Hashmap *h, const void *key, void **rkey);
static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) { static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) {
return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey); return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey);
} }
void *_hashmap_remove_value(HashmapBase *h, const void *key, void *value); void* _hashmap_remove_value(HashmapBase *h, const void *key, void *value);
static inline void *hashmap_remove_value(Hashmap *h, const void *key, void *value) { static inline void *hashmap_remove_value(Hashmap *h, const void *key, void *value) {
return _hashmap_remove_value(HASHMAP_BASE(h), key, value); return _hashmap_remove_value(HASHMAP_BASE(h), key, value);
} }
static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) { static inline void* ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) {
return hashmap_remove_value(PLAIN_HASHMAP(h), key, value); return hashmap_remove_value(PLAIN_HASHMAP(h), key, value);
} }
@@ -388,13 +391,13 @@ static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
}) })
/* no hashmap_next */ /* no hashmap_next */
void *ordered_hashmap_next(OrderedHashmap *h, const void *key); void* ordered_hashmap_next(OrderedHashmap *h, const void *key);
char **_hashmap_get_strv(HashmapBase *h); char** _hashmap_get_strv(HashmapBase *h);
static inline char **hashmap_get_strv(Hashmap *h) { static inline char** hashmap_get_strv(Hashmap *h) {
return _hashmap_get_strv(HASHMAP_BASE(h)); return _hashmap_get_strv(HASHMAP_BASE(h));
} }
static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { static inline char** ordered_hashmap_get_strv(OrderedHashmap *h) {
return _hashmap_get_strv(HASHMAP_BASE(h)); return _hashmap_get_strv(HASHMAP_BASE(h));
} }
@@ -404,17 +407,25 @@ static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) {
* the entries were inserted. * the entries were inserted.
* It is safe to remove the current entry. * It is safe to remove the current entry.
*/ */
#define HASHMAP_FOREACH(e, h, i) \ #define _HASHMAP_FOREACH(e, h, i) \
for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); ) for (Iterator i = ITERATOR_FIRST; hashmap_iterate((h), &i, (void**)&(e), NULL); )
#define HASHMAP_FOREACH(e, h) \
_HASHMAP_FOREACH(e, h, UNIQ_T(i, UNIQ))
#define ORDERED_HASHMAP_FOREACH(e, h, i) \ #define _ORDERED_HASHMAP_FOREACH(e, h, i) \
for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); ) for (Iterator i = ITERATOR_FIRST; ordered_hashmap_iterate((h), &i, (void**)&(e), NULL); )
#define ORDERED_HASHMAP_FOREACH(e, h) \
_ORDERED_HASHMAP_FOREACH(e, h, UNIQ_T(i, UNIQ))
#define HASHMAP_FOREACH_KEY(e, k, h, i) \ #define _HASHMAP_FOREACH_KEY(e, k, h, i) \
for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) for (Iterator i = ITERATOR_FIRST; hashmap_iterate((h), &i, (void**)&(e), (const void**) &(k)); )
#define HASHMAP_FOREACH_KEY(e, k, h) \
_HASHMAP_FOREACH_KEY(e, k, h, UNIQ_T(i, UNIQ))
#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ #define _ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \
for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) for (Iterator i = ITERATOR_FIRST; ordered_hashmap_iterate((h), &i, (void**)&(e), (const void**) &(k)); )
#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h) \
_ORDERED_HASHMAP_FOREACH_KEY(e, k, h, UNIQ_T(i, UNIQ))
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free);

View File

@@ -56,6 +56,16 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) {
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
} }
bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a) {
assert(a);
/* ff02::1 */
return be32toh(a->s6_addr32[0]) == UINT32_C(0xff020000) &&
a->s6_addr32[1] == 0 &&
a->s6_addr32[2] == 0 &&
be32toh(a->s6_addr32[3]) == UINT32_C(0x00000001);
}
int in_addr_is_multicast(int family, const union in_addr_union *u) { int in_addr_is_multicast(int family, const union in_addr_union *u) {
assert(u); assert(u);
@@ -68,6 +78,12 @@ int in_addr_is_multicast(int family, const union in_addr_union *u) {
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
} }
bool in4_addr_is_local_multicast(const struct in_addr *a) {
assert(a);
return (be32toh(a->s_addr) & UINT32_C(0xffffff00)) == UINT32_C(0xe0000000);
}
bool in4_addr_is_localhost(const struct in_addr *a) { bool in4_addr_is_localhost(const struct in_addr *a) {
assert(a); assert(a);
@@ -408,46 +424,6 @@ int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned
} }
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
_cleanup_free_ char *x = NULL;
size_t l;
int r;
assert(u);
assert(ret);
/* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly
* handle IPv6 link-local addresses. */
if (family != AF_INET6)
goto fallback;
if (ifindex <= 0)
goto fallback;
r = in_addr_is_link_local(family, u);
if (r < 0)
return r;
if (r == 0)
goto fallback;
l = INET6_ADDRSTRLEN + 1 + DECIMAL_STR_MAX(ifindex) + 1;
x = new(char, l);
if (!x)
return -ENOMEM;
errno = 0;
if (!inet_ntop(family, u, x, l))
return errno_or_else(EINVAL);
sprintf(strchr(x, 0), "%%%i", ifindex);
*ret = TAKE_PTR(x);
return 0;
fallback:
return in_addr_to_string(family, u, ret);
}
int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret) { int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret) {
_cleanup_free_ char *ip_str = NULL, *x = NULL; _cleanup_free_ char *ip_str = NULL, *x = NULL;
int r; int r;
@@ -802,13 +778,13 @@ static int in_addr_data_compare_func(const struct in_addr_data *x, const struct
DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func); DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func);
static void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) { void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
assert(addr); assert(addr);
siphash24_compress(addr, sizeof(*addr), state); siphash24_compress(addr, sizeof(*addr), state);
} }
static int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) { int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
return memcmp(a, b, sizeof(*a)); return memcmp(a, b, sizeof(*a));
} }

View File

@@ -12,6 +12,7 @@
union in_addr_union { union in_addr_union {
struct in_addr in; struct in_addr in;
struct in6_addr in6; struct in6_addr in6;
uint8_t bytes[CONST_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))];
}; };
struct in_addr_data { struct in_addr_data {
@@ -26,10 +27,12 @@ int in_addr_is_multicast(int family, const union in_addr_union *u);
bool in4_addr_is_link_local(const struct in_addr *a); bool in4_addr_is_link_local(const struct in_addr *a);
int in_addr_is_link_local(int family, const union in_addr_union *u); int in_addr_is_link_local(int family, const union in_addr_union *u);
bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a);
bool in4_addr_is_localhost(const struct in_addr *a); bool in4_addr_is_localhost(const struct in_addr *a);
int in_addr_is_localhost(int family, const union in_addr_union *u); int in_addr_is_localhost(int family, const union in_addr_union *u);
bool in4_addr_is_local_multicast(const struct in_addr *a);
bool in4_addr_is_non_local(const struct in_addr *a); bool in4_addr_is_non_local(const struct in_addr *a);
bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b); bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b);
@@ -40,8 +43,13 @@ int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, u
int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen); int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen);
int in_addr_to_string(int family, const union in_addr_union *u, char **ret); int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret); int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret);
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret);
int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret); int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret);
static inline int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
return in_addr_port_ifindex_name_to_string(family, u, 0, ifindex, NULL, ret);
}
static inline int in_addr_port_to_string(int family, const union in_addr_union *u, uint16_t port, char **ret) {
return in_addr_port_ifindex_name_to_string(family, u, port, 0, NULL, ret);
}
int in_addr_from_string(int family, const char *s, union in_addr_union *ret); int in_addr_from_string(int family, const char *s, union in_addr_union *ret);
int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret); int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret);
@@ -74,5 +82,8 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) {
* See also oss-fuzz#11344. */ * See also oss-fuzz#11344. */
#define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} }) #define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} })
void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state);
int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b);
extern const struct hash_ops in_addr_data_hash_ops; extern const struct hash_ops in_addr_data_hash_ops;
extern const struct hash_ops in6_addr_hash_ops; extern const struct hash_ops in6_addr_hash_ops;

View File

@@ -158,10 +158,8 @@ int pipe_eof(int fd) {
int r; int r;
r = fd_wait_for_event(fd, POLLIN, 0); r = fd_wait_for_event(fd, POLLIN, 0);
if (r < 0) if (r <= 0)
return r; return r;
if (r == 0)
return 0;
return !!(r & POLLHUP); return !!(r & POLLHUP);
} }

View File

@@ -248,12 +248,12 @@ void log_assert_failed_return_realm(
#define log_full_errno(level, error, ...) \ #define log_full_errno(level, error, ...) \
log_full_errno_realm(LOG_REALM, (level), (error), __VA_ARGS__) log_full_errno_realm(LOG_REALM, (level), (error), __VA_ARGS__)
#define log_full(level, ...) log_full_errno((level), 0, __VA_ARGS__) #define log_full(level, ...) (void) log_full_errno((level), 0, __VA_ARGS__)
int log_emergency_level(void); int log_emergency_level(void);
/* Normal logging */ /* Normal logging */
#define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__) #define log_debug(...) log_full_errno(LOG_DEBUG, 0, __VA_ARGS__)
#define log_info(...) log_full(LOG_INFO, __VA_ARGS__) #define log_info(...) log_full(LOG_INFO, __VA_ARGS__)
#define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__) #define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__)
#define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__) #define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__)

View File

@@ -547,6 +547,9 @@ static inline int __coverity_check_and_return__(int condition) {
(y) = (_t); \ (y) = (_t); \
} while (false) } while (false)
#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
/* Iterates through a specified list of pointers. Accepts NULL pointers, but uses (void*) -1 as internal marker for EOL. */ /* Iterates through a specified list of pointers. Accepts NULL pointers, but uses (void*) -1 as internal marker for EOL. */
#define FOREACH_POINTER(p, x, ...) \ #define FOREACH_POINTER(p, x, ...) \
for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, (void*) -1 }; \ for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, (void*) -1 }; \

View File

@@ -65,6 +65,10 @@ struct sockaddr_vm {
#define IP_TRANSPARENT 19 #define IP_TRANSPARENT 19
#endif #endif
#ifndef IPV6_FREEBIND
#define IPV6_FREEBIND 78
#endif
/* linux/sockios.h */ /* linux/sockios.h */
#ifndef SIOCGSKNS #ifndef SIOCGSKNS
#define SIOCGSKNS 0x894C #define SIOCGSKNS 0x894C

View File

@@ -9,45 +9,129 @@
#include <linux/stat.h> #include <linux/stat.h>
#endif #endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ /* Thew newest definition we are aware of (fa2fcf4f1df1559a0a4ee0f46915b496cc2ebf60; 5.8) */
#define STATX_DEFINITION { \
__u32 stx_mask; \
__u32 stx_blksize; \
__u64 stx_attributes; \
__u32 stx_nlink; \
__u32 stx_uid; \
__u32 stx_gid; \
__u16 stx_mode; \
__u16 __spare0[1]; \
__u64 stx_ino; \
__u64 stx_size; \
__u64 stx_blocks; \
__u64 stx_attributes_mask; \
struct statx_timestamp stx_atime; \
struct statx_timestamp stx_btime; \
struct statx_timestamp stx_ctime; \
struct statx_timestamp stx_mtime; \
__u32 stx_rdev_major; \
__u32 stx_rdev_minor; \
__u32 stx_dev_major; \
__u32 stx_dev_minor; \
__u64 stx_mnt_id; \
__u64 __spare2; \
__u64 __spare3[12]; \
}
#if !HAVE_STRUCT_STATX #if !HAVE_STRUCT_STATX
struct statx_timestamp { struct statx_timestamp {
__s64 tv_sec; __s64 tv_sec;
__u32 tv_nsec; __u32 tv_nsec;
__s32 __reserved; __s32 __reserved;
}; };
struct statx {
__u32 stx_mask; struct statx STATX_DEFINITION;
__u32 stx_blksize;
__u64 stx_attributes;
__u32 stx_nlink;
__u32 stx_uid;
__u32 stx_gid;
__u16 stx_mode;
__u16 __spare0[1];
__u64 stx_ino;
__u64 stx_size;
__u64 stx_blocks;
__u64 stx_attributes_mask;
struct statx_timestamp stx_atime;
struct statx_timestamp stx_btime;
struct statx_timestamp stx_ctime;
struct statx_timestamp stx_mtime;
__u32 stx_rdev_major;
__u32 stx_rdev_minor;
__u32 stx_dev_major;
__u32 stx_dev_minor;
__u64 __spare2[14];
};
#endif #endif
/* Always define the newest version we are aware of as a distinct type, so that we can use it even if glibc
* defines an older definition */
struct new_statx STATX_DEFINITION;
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ /* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_BTIME #ifndef AT_STATX_SYNC_AS_STAT
#define STATX_BTIME 0x00000800U #define AT_STATX_SYNC_AS_STAT 0x0000
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef AT_STATX_FORCE_SYNC
#define AT_STATX_FORCE_SYNC 0x2000
#endif #endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ /* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef AT_STATX_DONT_SYNC #ifndef AT_STATX_DONT_SYNC
#define AT_STATX_DONT_SYNC 0x4000 #define AT_STATX_DONT_SYNC 0x4000
#endif #endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_TYPE
#define STATX_TYPE 0x00000001U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_MODE
#define STATX_MODE 0x00000002U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_NLINK
#define STATX_NLINK 0x00000004U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_UID
#define STATX_UID 0x00000008U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_GID
#define STATX_GID 0x00000010U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_ATIME
#define STATX_ATIME 0x00000020U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_MTIME
#define STATX_MTIME 0x00000040U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_CTIME
#define STATX_CTIME 0x00000080U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_INO
#define STATX_INO 0x00000100U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_SIZE
#define STATX_SIZE 0x00000200U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_BLOCKS
#define STATX_BLOCKS 0x00000400U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_BTIME
#define STATX_BTIME 0x00000800U
#endif
/* fa2fcf4f1df1559a0a4ee0f46915b496cc2ebf60 (5.8) */
#ifndef STATX_MNT_ID
#define STATX_MNT_ID 0x00001000U
#endif
/* 80340fe3605c0e78cfe496c3b3878be828cfdbfe (5.8) */
#ifndef STATX_ATTR_MOUNT_ROOT
#define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */
#endif

View File

@@ -35,39 +35,49 @@ static inline int missing_pivot_root(const char *new_root, const char *put_old)
/* ======================================================================= */ /* ======================================================================= */
#if !HAVE_MEMFD_CREATE #if defined __x86_64__
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ # define systemd_NR_memfd_create 319
# if ! (defined __NR_memfd_create && __NR_memfd_create >= 0) #elif defined __arm__
# if defined __NR_memfd_create # define systemd_NR_memfd_create 385
# undef __NR_memfd_create #elif defined __aarch64__
# endif # define systemd_NR_memfd_create 279
# if defined __x86_64__ #elif defined(__powerpc__)
# define __NR_memfd_create 319 # define systemd_NR_memfd_create 360
# elif defined __arm__ #elif defined __s390__
# define __NR_memfd_create 385 # define systemd_NR_memfd_create 350
# elif defined __aarch64__ #elif defined _MIPS_SIM
# define __NR_memfd_create 279 # if _MIPS_SIM == _MIPS_SIM_ABI32
# elif defined __s390__ # define systemd_NR_memfd_create 4354
# 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
# elif defined __arc__
# define __NR_memfd_create 279
# else
# warning "__NR_memfd_create unknown for your architecture"
# endif
# endif # endif
# if _MIPS_SIM == _MIPS_SIM_NABI32
# define systemd_NR_memfd_create 6318
# endif
# if _MIPS_SIM == _MIPS_SIM_ABI64
# define systemd_NR_memfd_create 5314
# endif
#elif defined __i386__
# define systemd_NR_memfd_create 356
#elif defined __arc__
# define systemd_NR_memfd_create 279
#else
# warning "memfd_create() syscall number unknown for your architecture"
#endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
#if defined __NR_memfd_create && __NR_memfd_create >= 0
# if defined systemd_NR_memfd_create
assert_cc(__NR_memfd_create == systemd_NR_memfd_create);
# endif
#else
# if defined __NR_memfd_create
# undef __NR_memfd_create
# endif
# if defined systemd_NR_memfd_create
# define __NR_memfd_create systemd_NR_memfd_create
# endif
#endif
#if !HAVE_MEMFD_CREATE
static inline int missing_memfd_create(const char *name, unsigned int flags) { static inline int missing_memfd_create(const char *name, unsigned int flags) {
# ifdef __NR_memfd_create # ifdef __NR_memfd_create
return syscall(__NR_memfd_create, name, flags); return syscall(__NR_memfd_create, name, flags);
@@ -82,45 +92,53 @@ static inline int missing_memfd_create(const char *name, unsigned int flags) {
/* ======================================================================= */ /* ======================================================================= */
#if !HAVE_GETRANDOM #if defined __x86_64__
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ # define systemd_NR_getrandom 318
# if ! (defined __NR_getrandom && __NR_getrandom >= 0) #elif defined(__i386__)
# if defined __NR_getrandom # define systemd_NR_getrandom 355
# undef __NR_getrandom #elif defined(__arm__)
# endif # define systemd_NR_getrandom 384
# if defined __x86_64__ #elif defined(__aarch64__)
# define __NR_getrandom 318 # define systemd_NR_getrandom 278
# elif defined(__i386__) #elif defined(__ia64__)
# define __NR_getrandom 355 # define systemd_NR_getrandom 1339
# elif defined(__arm__) #elif defined(__m68k__)
# define __NR_getrandom 384 # define systemd_NR_getrandom 352
# elif defined(__aarch64__) #elif defined(__s390x__)
# define __NR_getrandom 278 # define systemd_NR_getrandom 349
# elif defined(__ia64__) #elif defined(__powerpc__)
# define __NR_getrandom 1339 # define systemd_NR_getrandom 359
# elif defined(__m68k__) #elif defined _MIPS_SIM
# define __NR_getrandom 352 # if _MIPS_SIM == _MIPS_SIM_ABI32
# elif defined(__s390x__) # define systemd_NR_getrandom 4353
# 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
# elif defined(__arc__)
# define __NR_getrandom 278
# else
# warning "__NR_getrandom unknown for your architecture"
# endif
# endif # endif
# if _MIPS_SIM == _MIPS_SIM_NABI32
# define systemd_NR_getrandom 6317
# endif
# if _MIPS_SIM == _MIPS_SIM_ABI64
# define systemd_NR_getrandom 5313
# endif
#elif defined(__arc__)
# define systemd_NR_getrandom 278
#else
# warning "getrandom() syscall number unknown for your architecture"
#endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
#if defined __NR_getrandom && __NR_getrandom >= 0
# if defined systemd_NR_getrandom
assert_cc(__NR_getrandom == systemd_NR_getrandom);
# endif
#else
# if defined __NR_getrandom
# undef __NR_getrandom
# endif
# if defined systemd_NR_getrandom
# define __NR_getrandom systemd_NR_getrandom
# endif
#endif
#if !HAVE_GETRANDOM
static inline int missing_getrandom(void *buffer, size_t count, unsigned flags) { static inline int missing_getrandom(void *buffer, size_t count, unsigned flags) {
# ifdef __NR_getrandom # ifdef __NR_getrandom
return syscall(__NR_getrandom, buffer, count, flags); return syscall(__NR_getrandom, buffer, count, flags);
@@ -135,9 +153,14 @@ static inline int missing_getrandom(void *buffer, size_t count, unsigned flags)
/* ======================================================================= */ /* ======================================================================= */
/* The syscall has been defined since forever, but the glibc wrapper was missing. */
#if !HAVE_GETTID #if !HAVE_GETTID
static inline pid_t missing_gettid(void) { static inline pid_t missing_gettid(void) {
# if defined __NR_gettid && __NR_gettid >= 0
return (pid_t) syscall(__NR_gettid); return (pid_t) syscall(__NR_gettid);
# else
# error "__NR_gettid not defined"
# endif
} }
# define gettid missing_gettid # define gettid missing_gettid
@@ -145,27 +168,39 @@ static inline pid_t missing_gettid(void) {
/* ======================================================================= */ /* ======================================================================= */
#if !HAVE_NAME_TO_HANDLE_AT #if defined(__x86_64__)
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ # define systemd_NR_name_to_handle_at 303
# if ! (defined __NR_name_to_handle_at && __NR_name_to_handle_at >= 0) #elif defined(__i386__)
# if defined __NR_name_to_handle_at # define systemd_NR_name_to_handle_at 341
# undef __NR_name_to_handle_at #elif defined(__arm__)
# endif # define systemd_NR_name_to_handle_at 370
# if defined(__x86_64__) #elif defined __aarch64__
# define __NR_name_to_handle_at 303 # define systemd_NR_name_to_handle_at 264
# elif defined(__i386__) #elif defined(__powerpc__)
# define __NR_name_to_handle_at 341 # define systemd_NR_name_to_handle_at 345
# elif defined(__arm__) #elif defined __s390__ || defined __s390x__
# define __NR_name_to_handle_at 370 # define systemd_NR_name_to_handle_at 335
# elif defined(__powerpc__) #elif defined(__arc__)
# define __NR_name_to_handle_at 345 # define systemd_NR_name_to_handle_at 264
# elif defined(__arc__) #else
# define __NR_name_to_handle_at 264 # warning "name_to_handle_at number is not defined"
# else #endif
# error "__NR_name_to_handle_at is not defined"
# endif
# endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
#if defined __NR_name_to_handle_at && __NR_name_to_handle_at >= 0
# if defined systemd_NR_name_to_handle_at
assert_cc(__NR_name_to_handle_at == systemd_NR_name_to_handle_at);
# endif
#else
# if defined __NR_name_to_handle_at
# undef __NR_name_to_handle_at
# endif
# if defined systemd_NR_name_to_handle_at
# define __NR_name_to_handle_at systemd_NR_name_to_handle_at
# endif
#endif
#if !HAVE_NAME_TO_HANDLE_AT
struct file_handle { struct file_handle {
unsigned int handle_bytes; unsigned int handle_bytes;
int handle_type; int handle_type;
@@ -186,23 +221,39 @@ static inline int missing_name_to_handle_at(int fd, const char *name, struct fil
/* ======================================================================= */ /* ======================================================================= */
#if !HAVE_SETNS #if defined __aarch64__
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ # define systemd_NR_setns 268
# if ! (defined __NR_setns && __NR_setns >= 0) #elif defined __arm__
# if defined __NR_setns # define systemd_NR_setns 375
# undef __NR_setns #elif defined(__x86_64__)
# endif # define systemd_NR_setns 308
# if defined(__x86_64__) #elif defined(__i386__)
# define __NR_setns 308 # define systemd_NR_setns 346
# elif defined(__i386__) #elif defined(__powerpc__)
# define __NR_setns 346 # define systemd_NR_setns 350
# elif defined(__arc__) #elif defined __s390__ || defined __s390x__
# define __NR_setns 268 # define systemd_NR_setns 339
# else #elif defined(__arc__)
# error "__NR_setns is not defined" # define systemd_NR_setns 268
# endif #else
# endif # warning "setns() syscall number unknown for your architecture"
#endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
#if defined __NR_setns && __NR_setns >= 0
# if defined systemd_NR_setns
assert_cc(__NR_setns == systemd_NR_setns);
# endif
#else
# if defined __NR_setns
# undef __NR_setns
# endif
# if defined systemd_NR_setns
# define __NR_setns systemd_NR_setns
# endif
#endif
#if !HAVE_SETNS
static inline int missing_setns(int fd, int nstype) { static inline int missing_setns(int fd, int nstype) {
# ifdef __NR_setns # ifdef __NR_setns
return syscall(__NR_setns, fd, nstype); return syscall(__NR_setns, fd, nstype);
@@ -227,41 +278,49 @@ static inline pid_t raw_getpid(void) {
/* ======================================================================= */ /* ======================================================================= */
#if !HAVE_RENAMEAT2 #if defined __x86_64__
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ # define systemd_NR_renameat2 316
# if ! (defined __NR_renameat2 && __NR_renameat2 >= 0) #elif defined __arm__
# if defined __NR_renameat2 # define systemd_NR_renameat2 382
# undef __NR_renameat2 #elif defined __aarch64__
# endif # define systemd_NR_renameat2 276
# if defined __x86_64__ #elif defined _MIPS_SIM
# define __NR_renameat2 316 # if _MIPS_SIM == _MIPS_SIM_ABI32
# elif defined __arm__ # define systemd_NR_renameat2 4351
# define __NR_renameat2 382
# elif defined __aarch64__
# define __NR_renameat2 276
# 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
# elif defined __powerpc64__
# define __NR_renameat2 357
# elif defined __s390__ || defined __s390x__
# define __NR_renameat2 347
# elif defined __arc__
# define __NR_renameat2 276
# else
# warning "__NR_renameat2 unknown for your architecture"
# endif
# endif # endif
# if _MIPS_SIM == _MIPS_SIM_NABI32
# define systemd_NR_renameat2 6315
# endif
# if _MIPS_SIM == _MIPS_SIM_ABI64
# define systemd_NR_renameat2 5311
# endif
#elif defined __i386__
# define systemd_NR_renameat2 353
#elif defined __powerpc64__
# define systemd_NR_renameat2 357
#elif defined __s390__ || defined __s390x__
# define systemd_NR_renameat2 347
#elif defined __arc__
# define systemd_NR_renameat2 276
#else
# warning "renameat2() syscall number unknown for your architecture"
#endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
#if defined __NR_renameat2 && __NR_renameat2 >= 0
# if defined systemd_NR_renameat2
assert_cc(__NR_renameat2 == systemd_NR_renameat2);
# endif
#else
# if defined __NR_renameat2
# undef __NR_renameat2
# endif
# if defined systemd_NR_renameat2
# define __NR_renameat2 systemd_NR_renameat2
# endif
#endif
#if !HAVE_RENAMEAT2
static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) { static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
# ifdef __NR_renameat2 # ifdef __NR_renameat2
return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags); return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
@@ -328,31 +387,39 @@ static inline key_serial_t missing_request_key(const char *type, const char *des
/* ======================================================================= */ /* ======================================================================= */
#if !HAVE_COPY_FILE_RANGE #if defined(__x86_64__)
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ # define systemd_NR_copy_file_range 326
# if ! (defined __NR_copy_file_range && __NR_copy_file_range >= 0) #elif defined(__i386__)
# if defined __NR_copy_file_range # define systemd_NR_copy_file_range 377
# undef __NR_copy_file_range #elif defined __s390__
# endif # define systemd_NR_copy_file_range 375
# if defined(__x86_64__) #elif defined __arm__
# define __NR_copy_file_range 326 # define systemd_NR_copy_file_range 391
# elif defined(__i386__) #elif defined __aarch64__
# define __NR_copy_file_range 377 # define systemd_NR_copy_file_range 285
# elif defined __s390__ #elif defined __powerpc__
# define __NR_copy_file_range 375 # define systemd_NR_copy_file_range 379
# elif defined __arm__ #elif defined __arc__
# define __NR_copy_file_range 391 # define systemd_NR_copy_file_range 285
# elif defined __aarch64__ #else
# define __NR_copy_file_range 285 # warning "copy_file_range() syscall number unknown for your architecture"
# elif defined __powerpc__ #endif
# define __NR_copy_file_range 379
# elif defined __arc__
# define __NR_copy_file_range 285
# else
# warning "__NR_copy_file_range not defined for your architecture"
# endif
# endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
#if defined __NR_copy_file_range && __NR_copy_file_range >= 0
# if defined systemd_NR_copy_file_range
assert_cc(__NR_copy_file_range == systemd_NR_copy_file_range);
# endif
#else
# if defined __NR_copy_file_range
# undef __NR_copy_file_range
# endif
# if defined systemd_NR_copy_file_range
# define __NR_copy_file_range systemd_NR_copy_file_range
# endif
#endif
#if !HAVE_COPY_FILE_RANGE
static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in, static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in,
int fd_out, loff_t *off_out, int fd_out, loff_t *off_out,
size_t len, size_t len,
@@ -370,31 +437,41 @@ static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in,
/* ======================================================================= */ /* ======================================================================= */
#if !HAVE_BPF #if defined __i386__
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ # define systemd_NR_bpf 357
# if ! (defined __NR_bpf && __NR_bpf >= 0) #elif defined __x86_64__
# if defined __NR_bpf # define systemd_NR_bpf 321
# undef __NR_bpf #elif defined __aarch64__
# endif # define systemd_NR_bpf 280
# if defined __i386__ #elif defined __arm__
# define __NR_bpf 357 # define systemd_NR_bpf 386
# elif defined __x86_64__ #elif defined(__powerpc__)
# define __NR_bpf 321 # define systemd_NR_bpf 361
# elif defined __aarch64__ #elif defined __sparc__
# define __NR_bpf 280 # define systemd_NR_bpf 349
# elif defined __arm__ #elif defined __s390__
# define __NR_bpf 386 # define systemd_NR_bpf 351
# elif defined __sparc__ #elif defined __tilegx__
# define __NR_bpf 349 # define systemd_NR_bpf 280
# elif defined __s390__ #else
# define __NR_bpf 351 # warning "bpf() syscall number unknown for your architecture"
# elif defined __tilegx__ #endif
# define __NR_bpf 280
# else
# warning "__NR_bpf not defined for your architecture"
# endif
# endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
#if defined __NR_bpf && __NR_bpf >= 0
# if defined systemd_NR_bpf
assert_cc(__NR_bpf == systemd_NR_bpf);
# endif
#else
# if defined __NR_bpf
# undef __NR_bpf
# endif
# if defined systemd_NR_bpf
# define __NR_bpf systemd_NR_bpf
# endif
#endif
#if !HAVE_BPF
union bpf_attr; union bpf_attr;
static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) { static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) {
@@ -412,69 +489,84 @@ static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) {
/* ======================================================================= */ /* ======================================================================= */
#ifndef __IGNORE_pkey_mprotect #ifndef __IGNORE_pkey_mprotect
# if defined __i386__
# define systemd_NR_pkey_mprotect 380
# elif defined __x86_64__
# define systemd_NR_pkey_mprotect 329
# elif defined __aarch64__
# define systemd_NR_pkey_mprotect 288
# elif defined __arm__
# define systemd_NR_pkey_mprotect 394
# elif defined __powerpc__
# define systemd_NR_pkey_mprotect 386
# elif defined __s390__
# define systemd_NR_pkey_mprotect 384
# elif defined _MIPS_SIM
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define systemd_NR_pkey_mprotect 4363
# endif
# if _MIPS_SIM == _MIPS_SIM_NABI32
# define systemd_NR_pkey_mprotect 6327
# endif
# if _MIPS_SIM == _MIPS_SIM_ABI64
# define systemd_NR_pkey_mprotect 5323
# endif
# else
# warning "pkey_mprotect() syscall number unknown for your architecture"
# endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ /* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_pkey_mprotect && __NR_pkey_mprotect >= 0) # if defined __NR_pkey_mprotect && __NR_pkey_mprotect >= 0
# if defined systemd_NR_pkey_mprotect
assert_cc(__NR_pkey_mprotect == systemd_NR_pkey_mprotect);
# endif
# else
# if defined __NR_pkey_mprotect # if defined __NR_pkey_mprotect
# undef __NR_pkey_mprotect # undef __NR_pkey_mprotect
# endif # endif
# if defined __i386__ # if defined systemd_NR_pkey_mprotect
# define __NR_pkey_mprotect 380 # define __NR_pkey_mprotect systemd_NR_pkey_mprotect
# elif defined __x86_64__
# define __NR_pkey_mprotect 329
# elif defined __arm__
# define __NR_pkey_mprotect 394
# elif defined __aarch64__
# define __NR_pkey_mprotect 394
# elif defined __powerpc__
# define __NR_pkey_mprotect 386
# elif defined __s390__
# define __NR_pkey_mprotect 384
# elif defined _MIPS_SIM
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define __NR_pkey_mprotect 4363
# endif
# if _MIPS_SIM == _MIPS_SIM_NABI32
# define __NR_pkey_mprotect 6327
# endif
# if _MIPS_SIM == _MIPS_SIM_ABI64
# define __NR_pkey_mprotect 5323
# endif
# else
# warning "__NR_pkey_mprotect not defined for your architecture"
# endif # endif
# endif # endif
#endif #endif
/* ======================================================================= */ /* ======================================================================= */
#if !HAVE_STATX #if defined __aarch64__
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ # define systemd_NR_statx 291
# if ! (defined __NR_statx && __NR_statx >= 0) #elif defined __arm__
# if defined __NR_statx # define systemd_NR_statx 397
# undef __NR_statx #elif defined __alpha__
# endif # define systemd_NR_statx 522
# if defined __aarch64__ || defined __arm__ #elif defined __i386__ || defined __powerpc64__
# define __NR_statx 397 # define systemd_NR_statx 383
# elif defined __alpha__ #elif defined __s390__ || defined __s390x__
# define __NR_statx 522 # define systemd_NR_statx 379
# elif defined __i386__ || defined __powerpc64__ #elif defined __sparc__
# define __NR_statx 383 # define systemd_NR_statx 360
# elif defined __sparc__ #elif defined __x86_64__
# define __NR_statx 360 # define systemd_NR_statx 332
# elif defined __x86_64__ #else
# define __NR_statx 332 # warning "statx() syscall number unknown for your architecture"
# else
# warning "__NR_statx not defined for your architecture"
# endif
# endif
struct statx;
#endif #endif
/* This typedef is supposed to be always defined. */ /* may be (invalid) negative number due to libseccomp, see PR 13319 */
typedef struct statx struct_statx; #if defined __NR_statx && __NR_statx >= 0
# if defined systemd_NR_statx
assert_cc(__NR_statx == systemd_NR_statx);
# endif
#else
# if defined __NR_statx
# undef __NR_statx
# endif
# if defined systemd_NR_statx
# define __NR_statx systemd_NR_statx
# endif
#endif
#if !HAVE_STATX #if !HAVE_STATX
struct statx;
static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) { static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) {
# ifdef __NR_statx # ifdef __NR_statx
return syscall(__NR_statx, dfd, filename, flags, mask, buffer); return syscall(__NR_statx, dfd, filename, flags, mask, buffer);
@@ -483,12 +575,18 @@ static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flag
return -1; return -1;
# endif # endif
} }
# define statx missing_statx
#endif #endif
#if !HAVE_SET_MEMPOLICY /* This typedef is supposed to be always defined. */
typedef struct statx struct_statx;
#if !HAVE_STATX
# define statx(dfd, filename, flags, mask, buffer) missing_statx(dfd, filename, flags, mask, buffer)
#endif
/* ======================================================================= */
#if !HAVE_SET_MEMPOLICY
enum { enum {
MPOL_DEFAULT, MPOL_DEFAULT,
MPOL_PREFERRED, MPOL_PREFERRED,
@@ -517,7 +615,7 @@ static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask,
unsigned long maxnode, void *addr, unsigned long maxnode, void *addr,
unsigned long flags) { unsigned long flags) {
long i; long i;
# ifdef __NR_get_mempolicy # if defined __NR_get_mempolicy && __NR_get_mempolicy >= 0
i = syscall(__NR_get_mempolicy, mode, nodemask, maxnode, addr, flags); i = syscall(__NR_get_mempolicy, mode, nodemask, maxnode, addr, flags);
# else # else
errno = ENOSYS; errno = ENOSYS;
@@ -526,49 +624,87 @@ static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask,
return i; return i;
} }
#define get_mempolicy missing_get_mempolicy # define get_mempolicy missing_get_mempolicy
#endif #endif
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */
#if !HAVE_PIDFD_OPEN /* ======================================================================= */
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_pidfd_open && __NR_pidfd_open >= 0) /* should be always defined, see kernel 39036cd2727395c3369b1051005da74059a85317 */
# if defined __NR_pidfd_open #if defined(__alpha__)
# undef __NR_pidfd_open # define systemd_NR_pidfd_send_signal 534
# endif
# define __NR_pidfd_open 434
#endif
static inline int pidfd_open(pid_t pid, unsigned flags) {
#ifdef __NR_pidfd_open
return syscall(__NR_pidfd_open, pid, flags);
#else #else
errno = ENOSYS; # define systemd_NR_pidfd_send_signal 424
return -1;
#endif #endif
}
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
#if defined __NR_pidfd_send_signal && __NR_pidfd_send_signal >= 0
# if defined systemd_NR_pidfd_send_signal
assert_cc(__NR_pidfd_send_signal == systemd_NR_pidfd_send_signal);
# endif
#else
# if defined __NR_pidfd_send_signal
# undef __NR_pidfd_send_signal
# endif
# define __NR_pidfd_send_signal systemd_NR_pidfd_send_signal
#endif #endif
#if !HAVE_PIDFD_SEND_SIGNAL #if !HAVE_PIDFD_SEND_SIGNAL
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ static inline int missing_pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) {
# if ! (defined __NR_pidfd_send_signal && __NR_pidfd_send_signal >= 0) # ifdef __NR_pidfd_open
# if defined __NR_pidfd_send_signal
# undef __NR_pidfd_send_signal
# endif
# define __NR_pidfd_send_signal 424
#endif
static inline int pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) {
#ifdef __NR_pidfd_open
return syscall(__NR_pidfd_send_signal, fd, sig, info, flags); return syscall(__NR_pidfd_send_signal, fd, sig, info, flags);
#else # else
errno = ENOSYS; errno = ENOSYS;
return -1; return -1;
#endif # endif
} }
# define pidfd_send_signal missing_pidfd_send_signal
#endif #endif
#if !HAVE_RT_SIGQUEUEINFO /* should be always defined, see kernel 7615d9e1780e26e0178c93c55b73309a5dc093d7 */
static inline int rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info) { #if defined(__alpha__)
return syscall(__NR_rt_sigqueueinfo, tgid, sig, info); # define systemd_NR_pidfd_open 544
} #else
# define systemd_NR_pidfd_open 434
#endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
#if defined __NR_pidfd_open && __NR_pidfd_open >= 0
# if defined systemd_NR_pidfd_open
assert_cc(__NR_pidfd_open == systemd_NR_pidfd_open);
# endif
#else
# if defined __NR_pidfd_open
# undef __NR_pidfd_open
# endif
# define __NR_pidfd_open systemd_NR_pidfd_open
#endif
#if !HAVE_PIDFD_OPEN
static inline int missing_pidfd_open(pid_t pid, unsigned flags) {
# ifdef __NR_pidfd_open
return syscall(__NR_pidfd_open, pid, flags);
# else
errno = ENOSYS;
return -1;
# endif
}
# define pidfd_open missing_pidfd_open
#endif
/* ======================================================================= */
#if !HAVE_RT_SIGQUEUEINFO
static inline int missing_rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info) {
# if defined __NR_rt_sigqueueinfo && __NR_rt_sigqueueinfo >= 0
return syscall(__NR_rt_sigqueueinfo, tgid, sig, info);
# else
# error "__NR_rt_sigqueueinfo not defined"
# endif
}
# define rt_sigqueueinfo missing_rt_sigqueueinfo
#endif #endif

View File

@@ -18,6 +18,9 @@
#include "missing_network.h" #include "missing_network.h"
#include "parse-util.h" #include "parse-util.h"
#include "process-util.h" #include "process-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
#include "stat-util.h" #include "stat-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
@@ -317,6 +320,7 @@ int parse_errno(const char *t) {
return e; return e;
} }
#if HAVE_SECCOMP
int parse_syscall_and_errno(const char *in, char **name, int *error) { int parse_syscall_and_errno(const char *in, char **name, int *error) {
_cleanup_free_ char *n = NULL; _cleanup_free_ char *n = NULL;
char *p; char *p;
@@ -335,7 +339,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) {
p = strchr(in, ':'); p = strchr(in, ':');
if (p) { if (p) {
e = parse_errno(p + 1); e = seccomp_parse_errno_or_action(p + 1);
if (e < 0) if (e < 0)
return e; return e;
@@ -354,6 +358,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) {
return 0; return 0;
} }
#endif
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */
static const char *mangle_base(const char *s, unsigned *base) { static const char *mangle_base(const char *s, unsigned *base) {

View File

@@ -19,7 +19,9 @@ int parse_mtu(int family, const char *s, uint32_t *ret);
int parse_size(const char *t, uint64_t base, uint64_t *size); int parse_size(const char *t, uint64_t base, uint64_t *size);
int parse_range(const char *t, unsigned *lower, unsigned *upper); int parse_range(const char *t, unsigned *lower, unsigned *upper);
int parse_errno(const char *t); int parse_errno(const char *t);
#if HAVE_SECCOMP
int parse_syscall_and_errno(const char *in, char **name, int *error); int parse_syscall_and_errno(const char *in, char **name, int *error);
#endif
#define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30) #define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30)
#define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29) #define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29)

View File

@@ -16,6 +16,7 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "extract-word.h" #include "extract-word.h"
#include "fd-util.h"
#include "fs-util.h" #include "fs-util.h"
#include "glob-util.h" #include "glob-util.h"
#include "log.h" #include "log.h"
@@ -29,15 +30,7 @@
#include "time-util.h" #include "time-util.h"
#include "utf8.h" #include "utf8.h"
bool path_is_absolute(const char *p) {
return p[0] == '/';
}
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
bool is_path(const char *p) {
return !!strchr(p, '/');
}
int path_split_and_make_absolute(const char *p, char ***ret) { int path_split_and_make_absolute(const char *p, char ***ret) {
char **l; char **l;
int r; int r;
@@ -601,9 +594,9 @@ char* path_join_internal(const char *first, ...) {
} }
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
int find_binary(const char *name, char **ret) { int find_executable_full(const char *name, bool use_path_envvar, char **ret) {
int last_error, r; int last_error, r;
const char *p; const char *p = NULL;
assert(name); assert(name);
@@ -620,11 +613,10 @@ int find_binary(const char *name, char **ret) {
return 0; return 0;
} }
/** if (use_path_envvar)
* Plain getenv, not secure_getenv, because we want /* Plain getenv, not secure_getenv, because we want to actually allow the user to pick the
* to actually allow the user to pick the binary. * binary. */
*/ p = getenv("PATH");
p = getenv("PATH");
if (!p) if (!p)
p = DEFAULT_PATH; p = DEFAULT_PATH;
@@ -647,12 +639,24 @@ int find_binary(const char *name, char **ret) {
return -ENOMEM; return -ENOMEM;
if (access(j, X_OK) >= 0) { if (access(j, X_OK) >= 0) {
/* Found it! */ _cleanup_free_ char *with_dash;
if (ret) with_dash = strjoin(j, "/");
*ret = path_simplify(TAKE_PTR(j), false); if (!with_dash)
return -ENOMEM;
return 0; /* If this passes, it must be a directory, and so should be skipped. */
if (access(with_dash, X_OK) >= 0)
continue;
/* We can't just `continue` inverting this case, since we need to update last_error. */
if (errno == ENOTDIR) {
/* Found it! */
if (ret)
*ret = path_simplify(TAKE_PTR(j), false);
return 0;
}
} }
/* PATH entries which we don't have access to are ignored, as per tradition. */ /* PATH entries which we don't have access to are ignored, as per tradition. */
@@ -698,18 +702,17 @@ bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool upd
return changed; return changed;
} }
static int binary_is_good(const char *binary) { static int executable_is_good(const char *executable) {
_cleanup_free_ char *p = NULL, *d = NULL; _cleanup_free_ char *p = NULL, *d = NULL;
int r; int r;
r = find_binary(binary, &p); r = find_executable(executable, &p);
if (r == -ENOENT) if (r == -ENOENT)
return 0; return 0;
if (r < 0) if (r < 0)
return r; return r;
/* An fsck that is linked to /bin/true is a non-existent /* An fsck that is linked to /bin/true is a non-existent fsck */
* fsck */
r = readlink_malloc(p, &d); r = readlink_malloc(p, &d);
if (r == -EINVAL) /* not a symlink */ if (r == -EINVAL) /* not a symlink */
@@ -732,19 +735,7 @@ int fsck_exists(const char *fstype) {
return -EINVAL; return -EINVAL;
checker = strjoina("fsck.", fstype); checker = strjoina("fsck.", fstype);
return binary_is_good(checker); return executable_is_good(checker);
}
int mkfs_exists(const char *fstype) {
const char *mkfs;
assert(fstype);
if (streq(fstype, "auto"))
return -EINVAL;
mkfs = strjoina("mkfs.", fstype);
return binary_is_good(mkfs);
} }
int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) { int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) {
@@ -1152,4 +1143,10 @@ bool prefixed_path_strv_contains(char **l, const char *path) {
return false; return false;
} }
bool credential_name_valid(const char *s) {
/* We want that credential names are both valid in filenames (since that's our primary way to pass
* them around) and as fdnames (which is how we might want to pass them around eventually) */
return filename_is_valid(s) && fdname_is_valid(s);
}
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -44,9 +44,17 @@
# define DEFAULT_USER_PATH DEFAULT_PATH # define DEFAULT_USER_PATH DEFAULT_PATH
#endif #endif
bool is_path(const char *p) _pure_; static inline bool is_path(const char *p) {
assert(p);
return strchr(p, '/');
}
static inline bool path_is_absolute(const char *p) {
assert(p);
return p[0] == '/';
}
int path_split_and_make_absolute(const char *p, char ***ret); int path_split_and_make_absolute(const char *p, char ***ret);
bool path_is_absolute(const char *p) _pure_;
char* path_make_absolute(const char *p, const char *prefix); char* path_make_absolute(const char *p, const char *prefix);
int safe_getcwd(char **ret); int safe_getcwd(char **ret);
int path_make_absolute_cwd(const char *p, char **ret); int path_make_absolute_cwd(const char *p, char **ret);
@@ -82,12 +90,14 @@ int path_strv_make_absolute_cwd(char **l);
char** path_strv_resolve(char **l, const char *root); char** path_strv_resolve(char **l, const char *root);
char** path_strv_resolve_uniq(char **l, const char *root); char** path_strv_resolve_uniq(char **l, const char *root);
int find_binary(const char *name, char **filename); int find_executable_full(const char *name, bool use_path_envvar, char **ret);
static inline int find_executable(const char *name, char **ret) {
return find_executable_full(name, true, ret);
}
bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update); bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);
int fsck_exists(const char *fstype); int fsck_exists(const char *fstype);
int mkfs_exists(const char *fstype);
/* Iterates through the path prefixes of the specified path, going up /* Iterates through the path prefixes of the specified path, going up
* the tree, to root. Also returns "" (and not "/"!) for the root * the tree, to root. Also returns "" (and not "/"!) for the root
@@ -176,3 +186,5 @@ static inline const char *empty_to_root(const char *path) {
bool path_strv_contains(char **l, const char *path); bool path_strv_contains(char **l, const char *path);
bool prefixed_path_strv_contains(char **l, const char *path); bool prefixed_path_strv_contains(char **l, const char *path);
bool credential_name_valid(const char *s);

View File

@@ -23,6 +23,7 @@
#endif #endif
#include "alloc-util.h" #include "alloc-util.h"
#include "env-util.h"
#include "errno-util.h" #include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
@@ -118,6 +119,15 @@ int rdrand(unsigned long *ret) {
#endif #endif
have_rdrand = !!(ecx & bit_RDRND); have_rdrand = !!(ecx & bit_RDRND);
if (have_rdrand > 0) {
/* Allow disabling use of RDRAND with SYSTEMD_RDRAND=0
If it is unset getenv_bool_secure will return a negative value. */
if (getenv_bool_secure("SYSTEMD_RDRAND") == 0) {
have_rdrand = false;
return -EOPNOTSUPP;
}
}
} }
if (have_rdrand == 0) if (have_rdrand == 0)

View File

@@ -13,14 +13,14 @@
0; \ 0; \
}) })
Set *_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); Set* _set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
#define set_new(ops) _set_new(ops HASHMAP_DEBUG_SRC_ARGS) #define set_new(ops) _set_new(ops HASHMAP_DEBUG_SRC_ARGS)
static inline Set *set_free(Set *s) { static inline Set* set_free(Set *s) {
return (Set*) _hashmap_free(HASHMAP_BASE(s), NULL, NULL); return (Set*) _hashmap_free(HASHMAP_BASE(s), NULL, NULL);
} }
static inline Set *set_free_free(Set *s) { static inline Set* set_free_free(Set *s) {
return (Set*) _hashmap_free(HASHMAP_BASE(s), free, NULL); return (Set*) _hashmap_free(HASHMAP_BASE(s), free, NULL);
} }
@@ -34,7 +34,7 @@ int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG
int set_put(Set *s, const void *key); int set_put(Set *s, const void *key);
/* no set_update */ /* no set_update */
/* no set_replace */ /* no set_replace */
static inline void *set_get(const Set *s, void *key) { static inline void *set_get(const Set *s, const void *key) {
return _hashmap_get(HASHMAP_BASE((Set *) s), key); return _hashmap_get(HASHMAP_BASE((Set *) s), key);
} }
/* no set_get2 */ /* no set_get2 */
@@ -77,7 +77,9 @@ static inline unsigned set_buckets(const Set *s) {
return _hashmap_buckets(HASHMAP_BASE((Set *) s)); return _hashmap_buckets(HASHMAP_BASE((Set *) s));
} }
bool set_iterate(const Set *s, Iterator *i, void **value); static inline bool set_iterate(const Set *s, Iterator *i, void **value) {
return _hashmap_iterate(HASHMAP_BASE((Set*) s), i, value, NULL);
}
static inline void set_clear(Set *s) { static inline void set_clear(Set *s) {
_hashmap_clear(HASHMAP_BASE(s), NULL, NULL); _hashmap_clear(HASHMAP_BASE(s), NULL, NULL);
@@ -133,8 +135,10 @@ int _set_put_strdupv(Set **s, char **l HASHMAP_DEBUG_PARAMS);
int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags); int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags);
#define SET_FOREACH(e, s, i) \ #define _SET_FOREACH(e, s, i) \
for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); ) for (Iterator i = ITERATOR_FIRST; set_iterate((s), &i, (void**)&(e)); )
#define SET_FOREACH(e, s) \
_SET_FOREACH(e, s, UNIQ_T(i, UNIQ))
#define SET_FOREACH_MOVE(e, d, s) \ #define SET_FOREACH_MOVE(e, d, s) \
for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); ) for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); )

View File

@@ -6,6 +6,8 @@
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include "time-util.h"
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
struct siphash { struct siphash {
uint64_t v0; uint64_t v0;
@@ -55,6 +57,10 @@ static inline void siphash24_compress_boolean(bool in, struct siphash *state) {
siphash24_compress(&i, sizeof i, state); siphash24_compress(&i, sizeof i, state);
} }
static inline void siphash24_compress_usec_t(usec_t in, struct siphash *state) {
siphash24_compress(&in, sizeof in, state);
}
static inline void siphash24_compress_string(const char *in, struct siphash *state) { static inline void siphash24_compress_string(const char *in, struct siphash *state) {
if (!in) if (!in)
return; return;

View File

@@ -30,6 +30,7 @@
#include "macro.h" #include "macro.h"
#include "memory-util.h" #include "memory-util.h"
#include "missing_socket.h" #include "missing_socket.h"
#include "missing_network.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "process-util.h" #include "process-util.h"
@@ -73,7 +74,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
if (a->sockaddr.in.sin_port == 0) if (a->sockaddr.in.sin_port == 0)
return -EINVAL; return -EINVAL;
if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
return -EINVAL; return -EINVAL;
return 0; return 0;
@@ -85,7 +86,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
if (a->sockaddr.in6.sin6_port == 0) if (a->sockaddr.in6.sin6_port == 0)
return -EINVAL; return -EINVAL;
if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
return -EINVAL; return -EINVAL;
return 0; return 0;
@@ -119,7 +120,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
} }
} }
if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET)) if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET))
return -EINVAL; return -EINVAL;
return 0; return 0;
@@ -129,7 +130,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
if (a->size != sizeof(struct sockaddr_nl)) if (a->size != sizeof(struct sockaddr_nl))
return -EINVAL; return -EINVAL;
if (!IN_SET(a->type, SOCK_RAW, SOCK_DGRAM)) if (!IN_SET(a->type, 0, SOCK_RAW, SOCK_DGRAM))
return -EINVAL; return -EINVAL;
return 0; return 0;
@@ -138,7 +139,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
if (a->size != sizeof(struct sockaddr_vm)) if (a->size != sizeof(struct sockaddr_vm))
return -EINVAL; return -EINVAL;
if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
return -EINVAL; return -EINVAL;
return 0; return 0;
@@ -404,19 +405,23 @@ int sockaddr_pretty(
if (r < 0) if (r < 0)
return -ENOMEM; return -ENOMEM;
} else { } else {
char a[INET6_ADDRSTRLEN]; char a[INET6_ADDRSTRLEN], ifname[IF_NAMESIZE + 1];
inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)); inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a));
if (sa->in6.sin6_scope_id != 0)
format_ifname_full(sa->in6.sin6_scope_id, ifname, FORMAT_IFNAME_IFINDEX);
if (include_port) { if (include_port) {
r = asprintf(&p, r = asprintf(&p,
"[%s]:%u", "[%s]:%u%s%s",
a, a,
be16toh(sa->in6.sin6_port)); be16toh(sa->in6.sin6_port),
sa->in6.sin6_scope_id != 0 ? "%" : "",
sa->in6.sin6_scope_id != 0 ? ifname : "");
if (r < 0) if (r < 0)
return -ENOMEM; return -ENOMEM;
} else { } else {
p = strdup(a); p = sa->in6.sin6_scope_id != 0 ? strjoin(a, "%", ifname) : strdup(a);
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
} }
@@ -622,40 +627,64 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b
return false; return false;
} }
int fd_inc_sndbuf(int fd, size_t n) { int fd_set_sndbuf(int fd, size_t n, bool increase) {
int r, value; int r, value;
socklen_t l = sizeof(value); socklen_t l = sizeof(value);
if (n > INT_MAX)
return -ERANGE;
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
return 0; return 0;
/* If we have the privileges we will ignore the kernel limit. */ /* First, try to set the buffer size with SO_SNDBUF. */
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n);
if (r < 0)
return r;
if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) { /* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n); * So, we need to check the actual buffer size here. */
if (r < 0) l = sizeof(value);
return r; r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
} if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
return 1;
/* If we have the privileges we will ignore the kernel limit. */
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
if (r < 0)
return r;
return 1; return 1;
} }
int fd_inc_rcvbuf(int fd, size_t n) { int fd_set_rcvbuf(int fd, size_t n, bool increase) {
int r, value; int r, value;
socklen_t l = sizeof(value); socklen_t l = sizeof(value);
if (n > INT_MAX)
return -ERANGE;
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
return 0; return 0;
/* If we have the privileges we will ignore the kernel limit. */ /* First, try to set the buffer size with SO_RCVBUF. */
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n);
if (r < 0)
return r;
if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) { /* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n); * So, we need to check the actual buffer size here. */
if (r < 0) l = sizeof(value);
return r; r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
} if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
return 1;
/* If we have the privileges we will ignore the kernel limit. */
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
if (r < 0)
return r;
return 1; return 1;
} }
@@ -669,17 +698,19 @@ static const char* const ip_tos_table[] = {
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
bool ifname_valid_full(const char *p, bool alternative) { bool ifname_valid_full(const char *p, IfnameValidFlags flags) {
bool numeric = true; bool numeric = true;
/* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources /* 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 * 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. */ * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
assert(!(flags & ~_IFNAME_VALID_ALL));
if (isempty(p)) if (isempty(p))
return false; return false;
if (alternative) { if (flags & IFNAME_VALID_ALTERNATIVE) {
if (strlen(p) >= ALTIFNAMSIZ) if (strlen(p) >= ALTIFNAMSIZ)
return false; return false;
} else { } else {
@@ -690,22 +721,27 @@ bool ifname_valid_full(const char *p, bool alternative) {
if (dot_or_dot_dot(p)) if (dot_or_dot_dot(p))
return false; return false;
while (*p) { for (const char *t = p; *t; t++) {
if ((unsigned char) *p >= 127U) if ((unsigned char) *t >= 127U)
return false; return false;
if ((unsigned char) *p <= 32U) if ((unsigned char) *t <= 32U)
return false; return false;
if (IN_SET(*p, ':', '/')) if (IN_SET(*t, ':', '/'))
return false; return false;
numeric = numeric && (*p >= '0' && *p <= '9'); numeric = numeric && (*t >= '0' && *t <= '9');
p++;
} }
if (numeric) if (numeric) {
return false; if (!(flags & IFNAME_VALID_NUMERIC))
return false;
/* Verify that the number is well-formatted and in range. */
if (parse_ifindex(p) < 0)
return false;
}
return true; return true;
} }
@@ -1095,12 +1131,10 @@ int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
* reference paths in the abstract namespace that include NUL bytes in the name. */ * reference paths in the abstract namespace that include NUL bytes in the name. */
l = strlen(path); l = strlen(path);
if (l == 0) if (l < 2)
return -EINVAL; return -EINVAL;
if (!IN_SET(path[0], '/', '@')) if (!IN_SET(path[0], '/', '@'))
return -EINVAL; return -EINVAL;
if (path[1] == 0)
return -EINVAL;
/* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than /* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than
* the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket * the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket
@@ -1183,13 +1217,28 @@ ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
return n; return n;
} }
int socket_pass_pktinfo(int fd, bool b) { int socket_get_family(int fd, int *ret) {
int af; int af;
socklen_t sl = sizeof(af); socklen_t sl = sizeof(af);
if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0) if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0)
return -errno; return -errno;
if (sl != sizeof(af))
return -EINVAL;
return af;
}
int socket_set_recvpktinfo(int fd, int af, bool b) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) { switch (af) {
case AF_INET: case AF_INET:
@@ -1205,3 +1254,142 @@ int socket_pass_pktinfo(int fd, bool b) {
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
} }
} }
int socket_set_recverr(int fd, int af, bool b) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
return setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, b);
case AF_INET6:
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVERR, b);
default:
return -EAFNOSUPPORT;
}
}
int socket_set_recvttl(int fd, int af, bool b) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
return setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, b);
case AF_INET6:
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, b);
default:
return -EAFNOSUPPORT;
}
}
int socket_set_ttl(int fd, int af, int ttl) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
return setsockopt_int(fd, IPPROTO_IP, IP_TTL, ttl);
case AF_INET6:
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, ttl);
default:
return -EAFNOSUPPORT;
}
}
int socket_set_unicast_if(int fd, int af, int ifi) {
be32_t ifindex_be = htobe32(ifi);
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
if (setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)) < 0)
return -errno;
return 0;
case AF_INET6:
if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)) < 0)
return -errno;
return 0;
default:
return -EAFNOSUPPORT;
}
}
int socket_set_freebind(int fd, int af, bool b) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
return setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, b);
case AF_INET6:
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_FREEBIND, b);
default:
return -EAFNOSUPPORT;
}
}
int socket_set_transparent(int fd, int af, bool b) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
return setsockopt_int(fd, IPPROTO_IP, IP_TRANSPARENT, b);
case AF_INET6:
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_TRANSPARENT, b);
default:
return -EAFNOSUPPORT;
}
}

View File

@@ -120,15 +120,26 @@ int netlink_family_from_string(const char *s) _pure_;
bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b); bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b);
int fd_inc_sndbuf(int fd, size_t n); int fd_set_sndbuf(int fd, size_t n, bool increase);
int fd_inc_rcvbuf(int fd, size_t n); static inline int fd_inc_sndbuf(int fd, size_t n) {
return fd_set_sndbuf(fd, n, true);
}
int fd_set_rcvbuf(int fd, size_t n, bool increase);
static inline int fd_inc_rcvbuf(int fd, size_t n) {
return fd_set_rcvbuf(fd, n, true);
}
int ip_tos_to_string_alloc(int i, char **s); int ip_tos_to_string_alloc(int i, char **s);
int ip_tos_from_string(const char *s); int ip_tos_from_string(const char *s);
bool ifname_valid_full(const char *p, bool alternative); typedef enum {
IFNAME_VALID_ALTERNATIVE = 1 << 0,
IFNAME_VALID_NUMERIC = 1 << 1,
_IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC,
} IfnameValidFlags;
bool ifname_valid_full(const char *p, IfnameValidFlags flags);
static inline bool ifname_valid(const char *p) { static inline bool ifname_valid(const char *p) {
return ifname_valid_full(p, false); return ifname_valid_full(p, 0);
} }
bool address_label_valid(const char *p); bool address_label_valid(const char *p);
@@ -207,6 +218,35 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \ strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \
}) })
#define SOCKADDR_LEN(sa) \
({ \
const union sockaddr_union *__sa = &(sa); \
size_t _len; \
switch(__sa->sa.sa_family) { \
case AF_INET: \
_len = sizeof(struct sockaddr_in); \
break; \
case AF_INET6: \
_len = sizeof(struct sockaddr_in6); \
break; \
case AF_UNIX: \
_len = SOCKADDR_UN_LEN(__sa->un); \
break; \
case AF_PACKET: \
_len = SOCKADDR_LL_LEN(__sa->ll); \
break; \
case AF_NETLINK: \
_len = sizeof(struct sockaddr_nl); \
break; \
case AF_VSOCK: \
_len = sizeof(struct sockaddr_vm); \
break; \
default: \
assert_not_reached("invalid socket family"); \
} \
_len; \
})
int socket_ioctl_fd(void); int socket_ioctl_fd(void);
int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path); int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path);
@@ -223,4 +263,11 @@ int socket_bind_to_ifindex(int fd, int ifindex);
ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags); ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags);
int socket_pass_pktinfo(int fd, bool b); int socket_get_family(int fd, int *ret);
int socket_set_recvpktinfo(int fd, int af, bool b);
int socket_set_recverr(int fd, int af, bool b);
int socket_set_recvttl(int fd, int af, bool b);
int socket_set_ttl(int fd, int af, int ttl);
int socket_set_unicast_if(int fd, int af, int ifi);
int socket_set_freebind(int fd, int af, bool b);
int socket_set_transparent(int fd, int af, bool b);

View File

@@ -17,6 +17,7 @@
#include "macro.h" #include "macro.h"
#include "missing_fs.h" #include "missing_fs.h"
#include "missing_magic.h" #include "missing_magic.h"
#include "missing_syscall.h"
#include "parse-util.h" #include "parse-util.h"
#include "stat-util.h" #include "stat-util.h"
#include "string-util.h" #include "string-util.h"
@@ -420,4 +421,60 @@ bool stat_inode_unmodified(const struct stat *a, const struct stat *b) {
a->st_ino == b->st_ino && a->st_ino == b->st_ino &&
(!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */ (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */
} }
int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx) {
static bool avoid_statx = false;
struct stat st;
if (!avoid_statx) {
if (statx(dfd, path, flags, mask, sx) < 0) {
if (!ERRNO_IS_NOT_SUPPORTED(errno) && errno != EPERM)
return -errno;
/* If statx() is not supported or if we see EPERM (which might indicate seccomp
* filtering or so), let's do a fallback. Not that on EACCES we'll not fall back,
* since that is likely an indication of fs access issues, which we should
* propagate */
} else
return 0;
avoid_statx = true;
}
/* Only do fallback if fstatat() supports the flag too, or if it's one of the sync flags, which are
* OK to ignore */
if ((flags & ~(AT_EMPTY_PATH|AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW|
AT_STATX_SYNC_AS_STAT|AT_STATX_FORCE_SYNC|AT_STATX_DONT_SYNC)) != 0)
return -EOPNOTSUPP;
if (fstatat(dfd, path, &st, flags & (AT_EMPTY_PATH|AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW)) < 0)
return -errno;
*sx = (struct statx) {
.stx_mask = STATX_TYPE|STATX_MODE|
STATX_NLINK|STATX_UID|STATX_GID|
STATX_ATIME|STATX_MTIME|STATX_CTIME|
STATX_INO|STATX_SIZE|STATX_BLOCKS,
.stx_blksize = st.st_blksize,
.stx_nlink = st.st_nlink,
.stx_uid = st.st_uid,
.stx_gid = st.st_gid,
.stx_mode = st.st_mode,
.stx_ino = st.st_ino,
.stx_size = st.st_size,
.stx_blocks = st.st_blocks,
.stx_rdev_major = major(st.st_rdev),
.stx_rdev_minor = minor(st.st_rdev),
.stx_dev_major = major(st.st_dev),
.stx_dev_minor = minor(st.st_dev),
.stx_atime.tv_sec = st.st_atim.tv_sec,
.stx_atime.tv_nsec = st.st_atim.tv_nsec,
.stx_mtime.tv_sec = st.st_mtim.tv_sec,
.stx_mtime.tv_nsec = st.st_mtim.tv_nsec,
.stx_ctime.tv_sec = st.st_ctim.tv_sec,
.stx_ctime.tv_nsec = st.st_ctim.tv_nsec,
};
return 0;
}
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -10,6 +10,7 @@
#include <sys/vfs.h> #include <sys/vfs.h>
#include "macro.h" #include "macro.h"
#include "missing_stat.h"
int is_symlink(const char *path); int is_symlink(const char *path);
int is_dir(const char *path, bool follow); int is_dir(const char *path, bool follow);
@@ -91,3 +92,24 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret
int proc_mounted(void); int proc_mounted(void);
bool stat_inode_unmodified(const struct stat *a, const struct stat *b); bool stat_inode_unmodified(const struct stat *a, const struct stat *b);
int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx);
#if HAS_FEATURE_MEMORY_SANITIZER
# warning "Explicitly initializing struct statx, to work around msan limitation. Please remove as soon as msan has been updated to not require this."
# define STRUCT_STATX_DEFINE(var) \
struct statx var = {}
# define STRUCT_NEW_STATX_DEFINE(var) \
union { \
struct statx sx; \
struct new_statx nsx; \
} var = {}
#else
# define STRUCT_STATX_DEFINE(var) \
struct statx var
# define STRUCT_NEW_STATX_DEFINE(var) \
union { \
struct statx sx; \
struct new_statx nsx; \
} var
#endif

View File

@@ -10,12 +10,14 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "escape.h" #include "escape.h"
#include "extract-word.h"
#include "fileio.h" #include "fileio.h"
#include "gunicode.h" #include "gunicode.h"
#include "locale-util.h" #include "locale-util.h"
#include "macro.h" #include "macro.h"
#include "memory-util.h" #include "memory-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h"
#include "terminal-util.h" #include "terminal-util.h"
#include "utf8.h" #include "utf8.h"
#include "util.h" #include "util.h"
@@ -112,83 +114,6 @@ char* first_word(const char *s, const char *word) {
return (char*) p; return (char*) p;
} }
static size_t strcspn_escaped(const char *s, const char *reject) {
bool escaped = false;
int n;
for (n = 0; s[n] != '\0'; n++) {
if (escaped)
escaped = false;
else if (s[n] == '\\')
escaped = true;
else if (strchr(reject, s[n]))
break;
}
return n;
}
/* Split a string into words. */
const char* split(
const char **state,
size_t *l,
const char *separator,
SplitFlags flags) {
const char *current;
assert(state);
assert(l);
if (!separator)
separator = WHITESPACE;
current = *state;
if (*current == '\0') /* already at the end? */
return NULL;
current += strspn(current, separator); /* skip leading separators */
if (*current == '\0') { /* at the end now? */
*state = current;
return NULL;
}
if (FLAGS_SET(flags, SPLIT_QUOTES)) {
if (strchr(QUOTES, *current)) {
/* We are looking at a quote */
*l = strcspn_escaped(current + 1, CHAR_TO_STR(*current));
if (current[*l + 1] != *current ||
(current[*l + 2] != 0 && !strchr(separator, current[*l + 2]))) {
/* right quote missing or garbage at the end */
if (FLAGS_SET(flags, SPLIT_RELAX)) {
*state = current + *l + 1 + (current[*l + 1] != '\0');
return current + 1;
}
*state = current;
return NULL;
}
*state = current++ + *l + 2;
} else {
/* We are looking at a something that is not a quote */
*l = strcspn_escaped(current, separator);
if (current[*l] && !strchr(separator, current[*l]) && !FLAGS_SET(flags, SPLIT_RELAX)) {
/* unfinished escape */
*state = current;
return NULL;
}
*state = current + *l;
}
} else {
*l = strcspn(current, separator);
*state = current + *l;
}
return current;
}
char *strnappend(const char *s, const char *suffix, size_t b) { char *strnappend(const char *s, const char *suffix, size_t b) {
size_t a; size_t a;
char *r; char *r;
@@ -1216,4 +1141,31 @@ int string_extract_line(const char *s, size_t i, char **ret) {
c++; c++;
} }
} }
int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word) {
/* In the default mode with no separators specified, we split on whitespace and
* don't coalesce separators. */
const ExtractFlags flags = separators ? EXTRACT_DONT_COALESCE_SEPARATORS : 0;
const char *found = NULL;
for (const char *p = string;;) {
_cleanup_free_ char *w = NULL;
int r;
r = extract_first_word(&p, &w, separators, flags);
if (r < 0)
return r;
if (r == 0)
break;
found = strv_find(words, w);
if (found)
break;
}
if (ret_word)
*ret_word = found;
return !!found;
}
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -108,24 +108,6 @@ char *endswith_no_case(const char *s, const char *postfix) _pure_;
char *first_word(const char *s, const char *word) _pure_; char *first_word(const char *s, const char *word) _pure_;
typedef enum SplitFlags {
SPLIT_QUOTES = 0x01 << 0,
SPLIT_RELAX = 0x01 << 1,
} SplitFlags;
/* Smelly. Do not use this anymore. Use extract_first_word() instead! */
const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags);
/* Similar, don't use this anymore */
#define FOREACH_WORD(word, length, s, state) \
_FOREACH_WORD(word, length, s, WHITESPACE, 0, state)
#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
_FOREACH_WORD(word, length, s, separator, 0, state)
#define _FOREACH_WORD(word, length, s, separator, flags, state) \
for ((state) = (s), (word) = split(&(state), &(length), (separator), (flags)); (word); (word) = split(&(state), &(length), (separator), (flags)))
char *strnappend(const char *s, const char *suffix, size_t length); char *strnappend(const char *s, const char *suffix, size_t length);
char *strjoin_real(const char *x, ...) _sentinel_; char *strjoin_real(const char *x, ...) _sentinel_;
@@ -135,8 +117,8 @@ char *strjoin_real(const char *x, ...) _sentinel_;
({ \ ({ \
const char *_appendees_[] = { a, __VA_ARGS__ }; \ const char *_appendees_[] = { a, __VA_ARGS__ }; \
char *_d_, *_p_; \ char *_d_, *_p_; \
size_t _len_ = 0; \ size_t _len_ = 0; \
size_t _i_; \ size_t _i_; \
for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
_len_ += strlen(_appendees_[_i_]); \ _len_ += strlen(_appendees_[_i_]); \
_p_ = _d_ = newa(char, _len_ + 1); \ _p_ = _d_ = newa(char, _len_ + 1); \
@@ -152,7 +134,6 @@ char *delete_trailing_chars(char *s, const char *bad);
char *truncate_nl(char *s); char *truncate_nl(char *s);
static inline char *skip_leading_chars(const char *s, const char *bad) { static inline char *skip_leading_chars(const char *s, const char *bad) {
if (!s) if (!s)
return NULL; return NULL;
@@ -231,11 +212,9 @@ REENABLE_WARNING;
/* Like startswith(), but operates on arbitrary memory blocks */ /* Like startswith(), but operates on arbitrary memory blocks */
static inline void *memory_startswith(const void *p, size_t sz, const char *token) { static inline void *memory_startswith(const void *p, size_t sz, const char *token) {
size_t n;
assert(token); assert(token);
n = strlen(token); size_t n = strlen(token);
if (sz < n) if (sz < n)
return NULL; return NULL;
@@ -251,20 +230,17 @@ static inline void *memory_startswith(const void *p, size_t sz, const char *toke
* It works only for ASCII strings. * It works only for ASCII strings.
*/ */
static inline void *memory_startswith_no_case(const void *p, size_t sz, const char *token) { static inline void *memory_startswith_no_case(const void *p, size_t sz, const char *token) {
size_t n, i;
assert(token); assert(token);
n = strlen(token); size_t n = strlen(token);
if (sz < n) if (sz < n)
return NULL; return NULL;
assert(p); assert(p);
for (i = 0; i < n; i++) { for (size_t i = 0; i < n; i++)
if (ascii_tolower(((char *)p)[i]) != ascii_tolower(token[i])) if (ascii_tolower(((char *)p)[i]) != ascii_tolower(token[i]))
return NULL; return NULL;
}
return (uint8_t*) p + n; return (uint8_t*) p + n;
} }
@@ -286,3 +262,8 @@ char* string_erase(char *x);
int string_truncate_lines(const char *s, size_t n_lines, char **ret); int string_truncate_lines(const char *s, size_t n_lines, char **ret);
int string_extract_line(const char *s, size_t i, char **ret); int string_extract_line(const char *s, size_t i, char **ret);
int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word);
static inline int string_contains_word(const char *string, const char *separators, const char *word) {
return string_contains_word_strv(string, separators, STRV_MAKE(word), NULL);
}

View File

@@ -260,44 +260,6 @@ int strv_extend_strv_concat(char ***a, char * const *b, const char *suffix) {
} }
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */
char **strv_split_full(const char *s, const char *separator, SplitFlags flags) {
const char *word, *state;
size_t l;
size_t n, i;
char **r;
assert(s);
if (!separator)
separator = WHITESPACE;
s += strspn(s, separator);
if (isempty(s))
return new0(char*, 1);
n = 0;
_FOREACH_WORD(word, l, s, separator, flags, state)
n++;
r = new(char*, n+1);
if (!r)
return NULL;
i = 0;
_FOREACH_WORD(word, l, s, separator, flags, state) {
r[i] = strndup(word, l);
if (!r[i]) {
strv_free(r);
return NULL;
}
i++;
}
r[i] = NULL;
return r;
}
char **strv_split_newlines(const char *s) { char **strv_split_newlines(const char *s) {
char **l; char **l;
size_t n; size_t n;
@@ -321,8 +283,7 @@ char **strv_split_newlines(const char *s) {
return l; return l;
} }
#if 0 /* NM_IGNORED */ int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags) {
int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
_cleanup_strv_free_ char **l = NULL; _cleanup_strv_free_ char **l = NULL;
size_t n = 0, allocated = 0; size_t n = 0, allocated = 0;
int r; int r;
@@ -358,6 +319,7 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
return (int) n; return (int) n;
} }
#if 0 /* NM_IGNORED */
int strv_split_colon_pairs(char ***t, const char *s) { int strv_split_colon_pairs(char ***t, const char *s) {
_cleanup_strv_free_ char **l = NULL; _cleanup_strv_free_ char **l = NULL;
size_t n = 0, allocated = 0; size_t n = 0, allocated = 0;

View File

@@ -72,13 +72,19 @@ static inline bool strv_isempty(char * const *l) {
return !l || !*l; return !l || !*l;
} }
char **strv_split_full(const char *s, const char *separator, SplitFlags flags);
static inline char **strv_split(const char *s, const char *separator) {
return strv_split_full(s, separator, 0);
}
char **strv_split_newlines(const char *s); char **strv_split_newlines(const char *s);
int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags); int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags);
static inline char **strv_split(const char *s, const char *separators) {
char **ret;
int r;
r = strv_split_full(&ret, s, separators, 0);
if (r < 0)
return NULL;
return ret;
}
/* Given a string containing white-space separated tuples of words themselves separated by ':', /* Given a string containing white-space separated tuples of words themselves separated by ':',
* returns a vector of strings. If the second element in a tuple is missing, the corresponding * returns a vector of strings. If the second element in a tuple is missing, the corresponding
@@ -123,10 +129,6 @@ bool strv_overlap(char * const *a, char * const *b) _pure_;
char **strv_sort(char **l); char **strv_sort(char **l);
void strv_print(char * const *l); void strv_print(char * const *l);
#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
#define strv_from_stdarg_alloca(first) \ #define strv_from_stdarg_alloca(first) \
({ \ ({ \
char **_l; \ char **_l; \

View File

@@ -25,6 +25,7 @@
#include "path-util.h" #include "path-util.h"
#include "process-util.h" #include "process-util.h"
#include "stat-util.h" #include "stat-util.h"
#include "string-table.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "time-util.h" #include "time-util.h"
@@ -245,12 +246,28 @@ struct timespec *timespec_store(struct timespec *ts, usec_t u) {
if (u == USEC_INFINITY || if (u == USEC_INFINITY ||
u / USEC_PER_SEC >= TIME_T_MAX) { u / USEC_PER_SEC >= TIME_T_MAX) {
ts->tv_sec = (time_t) -1; ts->tv_sec = (time_t) -1;
ts->tv_nsec = (long) -1; ts->tv_nsec = -1L;
return ts; return ts;
} }
ts->tv_sec = (time_t) (u / USEC_PER_SEC); ts->tv_sec = (time_t) (u / USEC_PER_SEC);
ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC); ts->tv_nsec = (long) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
return ts;
}
struct timespec *timespec_store_nsec(struct timespec *ts, nsec_t n) {
assert(ts);
if (n == NSEC_INFINITY ||
n / NSEC_PER_SEC >= TIME_T_MAX) {
ts->tv_sec = (time_t) -1;
ts->tv_nsec = -1L;
return ts;
}
ts->tv_sec = (time_t) (n / NSEC_PER_SEC);
ts->tv_nsec = (long) (n % NSEC_PER_SEC);
return ts; return ts;
} }
@@ -285,12 +302,11 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) {
return tv; return tv;
} }
static char *format_timestamp_internal( char *format_timestamp_style(
char *buf, char *buf,
size_t l, size_t l,
usec_t t, usec_t t,
bool utc, TimestampStyle style) {
bool us) {
/* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our /* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our
* generated timestamps may be parsed with parse_timestamp(), and always read the same. */ * generated timestamps may be parsed with parse_timestamp(), and always read the same. */
@@ -307,9 +323,27 @@ static char *format_timestamp_internal(
struct tm tm; struct tm tm;
time_t sec; time_t sec;
size_t n; size_t n;
bool utc = false, us = false;
assert(buf); assert(buf);
switch (style) {
case TIMESTAMP_PRETTY:
break;
case TIMESTAMP_US:
us = true;
break;
case TIMESTAMP_UTC:
utc = true;
break;
case TIMESTAMP_US_UTC:
us = true;
utc = true;
break;
default:
return NULL;
}
if (l < (size_t) (3 + /* week day */ if (l < (size_t) (3 + /* week day */
1 + 10 + /* space and date */ 1 + 10 + /* space and date */
1 + 8 + /* space and time */ 1 + 8 + /* space and time */
@@ -383,22 +417,6 @@ static char *format_timestamp_internal(
return buf; return buf;
} }
char *format_timestamp(char *buf, size_t l, usec_t t) {
return format_timestamp_internal(buf, l, t, false, false);
}
char *format_timestamp_utc(char *buf, size_t l, usec_t t) {
return format_timestamp_internal(buf, l, t, true, false);
}
char *format_timestamp_us(char *buf, size_t l, usec_t t) {
return format_timestamp_internal(buf, l, t, false, true);
}
char *format_timestamp_us_utc(char *buf, size_t l, usec_t t) {
return format_timestamp_internal(buf, l, t, true, true);
}
char *format_timestamp_relative(char *buf, size_t l, usec_t t) { char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
const char *s; const char *s;
usec_t n, d; usec_t n, d;
@@ -1575,4 +1593,28 @@ int time_change_fd(void) {
return -errno; return -errno;
} }
static const char* const timestamp_style_table[_TIMESTAMP_STYLE_MAX] = {
[TIMESTAMP_PRETTY] = "pretty",
[TIMESTAMP_US] = "us",
[TIMESTAMP_UTC] = "utc",
[TIMESTAMP_US_UTC] = "us+utc",
};
/* Use the macro for enum → string to allow for aliases */
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(timestamp_style, TimestampStyle,);
/* For the string → enum mapping we use the generic implementation, but also support two aliases */
TimestampStyle timestamp_style_from_string(const char *s) {
TimestampStyle t;
t = (TimestampStyle) string_table_lookup(timestamp_style_table, ELEMENTSOF(timestamp_style_table), s);
if (t >= 0)
return t;
if (streq_ptr(s, "µs"))
return TIMESTAMP_US;
if (streq_ptr(s, "µs+uts"))
return TIMESTAMP_US_UTC;
return t;
}
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -29,6 +29,15 @@ typedef struct triple_timestamp {
usec_t boottime; usec_t boottime;
} triple_timestamp; } triple_timestamp;
typedef enum TimestampStyle {
TIMESTAMP_PRETTY,
TIMESTAMP_US,
TIMESTAMP_UTC,
TIMESTAMP_US_UTC,
_TIMESTAMP_STYLE_MAX,
_TIMESTAMP_STYLE_INVALID = -1,
} TimestampStyle;
#define USEC_INFINITY ((usec_t) UINT64_MAX) #define USEC_INFINITY ((usec_t) UINT64_MAX)
#define NSEC_INFINITY ((nsec_t) UINT64_MAX) #define NSEC_INFINITY ((nsec_t) UINT64_MAX)
@@ -103,17 +112,19 @@ usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock);
usec_t timespec_load(const struct timespec *ts) _pure_; usec_t timespec_load(const struct timespec *ts) _pure_;
nsec_t timespec_load_nsec(const struct timespec *ts) _pure_; nsec_t timespec_load_nsec(const struct timespec *ts) _pure_;
struct timespec *timespec_store(struct timespec *ts, usec_t u); struct timespec *timespec_store(struct timespec *ts, usec_t u);
struct timespec *timespec_store_nsec(struct timespec *ts, nsec_t n);
usec_t timeval_load(const struct timeval *tv) _pure_; usec_t timeval_load(const struct timeval *tv) _pure_;
struct timeval *timeval_store(struct timeval *tv, usec_t u); struct timeval *timeval_store(struct timeval *tv, usec_t u);
char *format_timestamp(char *buf, size_t l, usec_t t); char *format_timestamp_style(char *buf, size_t l, usec_t t, TimestampStyle style);
char *format_timestamp_utc(char *buf, size_t l, usec_t t);
char *format_timestamp_us(char *buf, size_t l, usec_t t);
char *format_timestamp_us_utc(char *buf, size_t l, usec_t t);
char *format_timestamp_relative(char *buf, size_t l, usec_t t); char *format_timestamp_relative(char *buf, size_t l, usec_t t);
char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy); char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
static inline char *format_timestamp(char *buf, size_t l, usec_t t) {
return format_timestamp_style(buf, l, t, TIMESTAMP_PRETTY);
}
int parse_timestamp(const char *t, usec_t *usec); int parse_timestamp(const char *t, usec_t *usec);
int parse_sec(const char *t, usec_t *usec); int parse_sec(const char *t, usec_t *usec);
@@ -185,3 +196,6 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) {
#endif #endif
int time_change_fd(void); int time_change_fd(void);
const char* timestamp_style_to_string(TimestampStyle t) _const_;
TimestampStyle timestamp_style_from_string(const char *s) _pure_;

View File

@@ -125,7 +125,7 @@ int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) {
return 0; return 0;
} }
bool utf8_is_printable_newline(const char* str, size_t length, bool newline) { bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) {
const char *p; const char *p;
assert(str); assert(str);
@@ -142,7 +142,7 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
r = utf8_encoded_to_unichar(p, &val); r = utf8_encoded_to_unichar(p, &val);
if (r < 0 || if (r < 0 ||
unichar_is_control(val) || unichar_is_control(val) ||
(!newline && val == '\n')) (!allow_newline && val == '\n'))
return false; return false;
length -= encoded_len; length -= encoded_len;
@@ -152,18 +152,22 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
return true; return true;
} }
char *utf8_is_valid(const char *str) { char *utf8_is_valid_n(const char *str, size_t len_bytes) {
const char *p; /* Check if the string is composed of valid utf8 characters. If length len_bytes is given, stop after
* len_bytes. Otherwise, stop at NUL. */
assert(str); assert(str);
p = str; for (const char *p = str; len_bytes != (size_t) -1 ? (size_t) (p - str) < len_bytes : *p != '\0'; ) {
while (*p) {
int len; int len;
len = utf8_encoded_valid_unichar(p, (size_t) -1); if (_unlikely_(*p == '\0') && len_bytes != (size_t) -1)
if (len < 0) return NULL; /* embedded NUL */
return NULL;
len = utf8_encoded_valid_unichar(p,
len_bytes != (size_t) -1 ? len_bytes - (p - str) : (size_t) -1);
if (_unlikely_(len < 0))
return NULL; /* invalid character */
p += len; p += len;
} }

View File

@@ -14,11 +14,14 @@
bool unichar_is_valid(char32_t c); bool unichar_is_valid(char32_t c);
char *utf8_is_valid(const char *s) _pure_; char *utf8_is_valid_n(const char *str, size_t len_bytes) _pure_;
static inline char *utf8_is_valid(const char *s) {
return utf8_is_valid_n(s, (size_t) -1);
}
char *ascii_is_valid(const char *s) _pure_; char *ascii_is_valid(const char *s) _pure_;
char *ascii_is_valid_n(const char *str, size_t len); char *ascii_is_valid_n(const char *str, size_t len);
bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_; bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) _pure_;
#define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true) #define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true)
char *utf8_escape_invalid(const char *s); char *utf8_escape_invalid(const char *s);

View File

@@ -78,7 +78,7 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_
assert(ifindex > 0); assert(ifindex > 0);
s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (s < 0) if (s < 0)
return -errno; return -errno;

View File

@@ -83,9 +83,8 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
OrderedHashmap *s = (OrderedHashmap *) optval; OrderedHashmap *s = (OrderedHashmap *) optval;
struct sd_dhcp_option *p; struct sd_dhcp_option *p;
size_t l = 0; size_t l = 0;
Iterator i;
ORDERED_HASHMAP_FOREACH(p, s, i) ORDERED_HASHMAP_FOREACH(p, s)
l += p->length + 2; l += p->length + 2;
if (*offset + l + 2 > size) if (*offset + l + 2 > size)
@@ -96,7 +95,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
*offset += 2; *offset += 2;
ORDERED_HASHMAP_FOREACH(p, s, i) { ORDERED_HASHMAP_FOREACH(p, s) {
options[*offset] = p->option; options[*offset] = p->option;
options[*offset + 1] = p->length; options[*offset + 1] = p->length;
memcpy(&options[*offset + 2], p->data, p->length); memcpy(&options[*offset + 2], p->data, p->length);

View File

@@ -83,7 +83,6 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options) { int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options) {
sd_dhcp6_option *options; sd_dhcp6_option *options;
Iterator i;
int r; int r;
assert(buf); assert(buf);
@@ -91,7 +90,7 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHash
assert(buflen); assert(buflen);
assert(vendor_options); assert(vendor_options);
ORDERED_HASHMAP_FOREACH(options, vendor_options, i) { ORDERED_HASHMAP_FOREACH(options, vendor_options) {
_cleanup_free_ uint8_t *p = NULL; _cleanup_free_ uint8_t *p = NULL;
size_t total; size_t total;

View File

@@ -49,7 +49,7 @@ int lldp_network_bind_raw_socket(int ifindex) {
assert(ifindex > 0); assert(ifindex > 0);
fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, fd = socket(AF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK,
htobe16(ETHERTYPE_LLDP)); htobe16(ETHERTYPE_LLDP));
if (fd < 0) if (fd < 0)
return -errno; return -errno;

View File

@@ -924,7 +924,6 @@ static int dhcp_client_send_raw(
static int client_append_common_discover_request_options(sd_dhcp_client *client, DHCPPacket *packet, size_t *optoffset, size_t optlen) { static int client_append_common_discover_request_options(sd_dhcp_client *client, DHCPPacket *packet, size_t *optoffset, size_t optlen) {
sd_dhcp_option *j; sd_dhcp_option *j;
Iterator i;
int r; int r;
assert(client); assert(client);
@@ -975,7 +974,7 @@ static int client_append_common_discover_request_options(sd_dhcp_client *client,
return r; return r;
} }
ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) { ORDERED_HASHMAP_FOREACH(j, client->extra_options) {
r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
j->option, j->length, j->data); j->option, j->length, j->data);
if (r < 0) if (r < 0)

View File

@@ -630,7 +630,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
struct sd_dhcp6_option *j; struct sd_dhcp6_option *j;
size_t len, optlen = 512; size_t len, optlen = 512;
Iterator i;
uint8_t *opt; uint8_t *opt;
int r; int r;
usec_t elapsed_usec; usec_t elapsed_usec;
@@ -865,7 +864,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
if (r < 0) if (r < 0)
return r; return r;
ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) { ORDERED_HASHMAP_FOREACH(j, client->extra_options) {
r = dhcp6_option_append(&opt, &optlen, j->option, j->length, j->data); r = dhcp6_option_append(&opt, &optlen, j->option, j->length, j->data);
if (r < 0) if (r < 0)
return r; return r;
@@ -1701,7 +1700,7 @@ int sd_dhcp6_client_is_running(sd_dhcp6_client *client) {
int sd_dhcp6_client_start(sd_dhcp6_client *client) { int sd_dhcp6_client_start(sd_dhcp6_client *client) {
enum DHCP6State state = DHCP6_STATE_SOLICITATION; enum DHCP6State state = DHCP6_STATE_SOLICITATION;
int r = 0; int r;
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
assert_return(client->event, -EINVAL); assert_return(client->event, -EINVAL);

View File

@@ -144,10 +144,17 @@ static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) {
} }
int sd_ipv4acd_stop(sd_ipv4acd *acd) { int sd_ipv4acd_stop(sd_ipv4acd *acd) {
IPv4ACDState old_state;
assert_return(acd, -EINVAL); assert_return(acd, -EINVAL);
old_state = acd->state;
ipv4acd_reset(acd); ipv4acd_reset(acd);
if (old_state == IPV4ACD_STATE_INIT)
return 0;
log_ipv4acd(acd, "STOPPED"); log_ipv4acd(acd, "STOPPED");
ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP); ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP);
@@ -437,6 +444,15 @@ int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address) {
return 0; return 0;
} }
int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address) {
assert_return(acd, -EINVAL);
assert_return(address, -EINVAL);
address->s_addr = acd->address;
return 0;
}
int sd_ipv4acd_is_running(sd_ipv4acd *acd) { int sd_ipv4acd_is_running(sd_ipv4acd *acd) {
assert_return(acd, false); assert_return(acd, false);
@@ -457,8 +473,7 @@ int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts) {
if (r < 0) if (r < 0)
return r; return r;
safe_close(acd->fd); CLOSE_AND_REPLACE(acd->fd, r);
acd->fd = r;
acd->defend_window = 0; acd->defend_window = 0;
if (reset_conflicts) if (reset_conflicts)

View File

@@ -433,7 +433,6 @@ static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) {
_public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) { _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
sd_lldp_neighbor **l = NULL, *n; sd_lldp_neighbor **l = NULL, *n;
Iterator i;
int k = 0, r; int k = 0, r;
assert_return(lldp, -EINVAL); assert_return(lldp, -EINVAL);
@@ -454,7 +453,7 @@ _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
return r; return r;
} }
HASHMAP_FOREACH(n, lldp->neighbor_by_id, i) HASHMAP_FOREACH(n, lldp->neighbor_by_id)
l[k++] = sd_lldp_neighbor_ref(n); l[k++] = sd_lldp_neighbor_ref(n);
assert((size_t) k == hashmap_size(lldp->neighbor_by_id)); assert((size_t) k == hashmap_size(lldp->neighbor_by_id));

View File

@@ -2874,7 +2874,6 @@ static int process_timer(
static int process_child(sd_event *e) { static int process_child(sd_event *e) {
sd_event_source *s; sd_event_source *s;
Iterator i;
int r; int r;
assert(e); assert(e);
@@ -2899,7 +2898,7 @@ static int process_child(sd_event *e) {
the callback still sees the process as a zombie. the callback still sees the process as a zombie.
*/ */
HASHMAP_FOREACH(s, e->child_sources, i) { HASHMAP_FOREACH(s, e->child_sources) {
assert(s->type == SOURCE_CHILD); assert(s->type == SOURCE_CHILD);
if (s->pending) if (s->pending)
@@ -3104,12 +3103,11 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) {
if (d->buffer.ev.mask & IN_Q_OVERFLOW) { if (d->buffer.ev.mask & IN_Q_OVERFLOW) {
struct inode_data *inode_data; struct inode_data *inode_data;
Iterator i;
/* The queue overran, let's pass this event to all event sources connected to this inotify /* The queue overran, let's pass this event to all event sources connected to this inotify
* object */ * object */
HASHMAP_FOREACH(inode_data, d->inodes, i) { HASHMAP_FOREACH(inode_data, d->inodes) {
sd_event_source *s; sd_event_source *s;
LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) {
@@ -3207,12 +3205,11 @@ static int source_dispatch(sd_event_source *s) {
if (s->type != SOURCE_POST) { if (s->type != SOURCE_POST) {
sd_event_source *z; sd_event_source *z;
Iterator i;
/* If we execute a non-post source, let's mark all /* If we execute a non-post source, let's mark all
* post sources as pending */ * post sources as pending */
SET_FOREACH(z, s->event->post_sources, i) { SET_FOREACH(z, s->event->post_sources) {
if (z->enabled == SD_EVENT_OFF) if (z->enabled == SD_EVENT_OFF)
continue; continue;