diff options
Diffstat (limited to 'shared/systemd/src/basic')
41 files changed, 441 insertions, 199 deletions
diff --git a/shared/systemd/src/basic/alloc-util.c b/shared/systemd/src/basic/alloc-util.c index c97d8700..e355b60f 100644 --- a/shared/systemd/src/basic/alloc-util.c +++ b/shared/systemd/src/basic/alloc-util.c @@ -80,7 +80,7 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { * take possession of the extra space. This should be cheap, since libc doesn't have to move * the memory for this. */ - qq = realloc(q, bn * size); + qq = reallocarray(q, bn, size); if (_likely_(qq)) { *p = qq; *allocated = bn; diff --git a/shared/systemd/src/basic/env-file.c b/shared/systemd/src/basic/env-file.c index 5860b050..30ee135a 100644 --- a/shared/systemd/src/basic/env-file.c +++ b/shared/systemd/src/basic/env-file.c @@ -488,6 +488,8 @@ static int merge_env_file_push( free_and_replace(value, expanded_value); + log_debug("%s:%u: setting %s=%s", filename, line, key, value); + return load_env_file_push(filename, line, key, value, env, n_pushed); } diff --git a/shared/systemd/src/basic/env-util.c b/shared/systemd/src/basic/env-util.c index cd9d3176..d16890d9 100644 --- a/shared/systemd/src/basic/env-util.c +++ b/shared/systemd/src/basic/env-util.c @@ -6,7 +6,6 @@ #include <limits.h> #include <stdarg.h> #include <stdlib.h> -#include <string.h> #include <unistd.h> #include "alloc-util.h" diff --git a/shared/systemd/src/basic/errno-util.h b/shared/systemd/src/basic/errno-util.h index 6053cde6..8f1be6c0 100644 --- a/shared/systemd/src/basic/errno-util.h +++ b/shared/systemd/src/basic/errno-util.h @@ -86,3 +86,18 @@ static inline bool ERRNO_IS_RESOURCE(int r) { ENFILE, ENOMEM); } + +/* Three different errors for "operation/system call/ioctl not supported" */ +static inline bool ERRNO_IS_NOT_SUPPORTED(int r) { + return IN_SET(abs(r), + EOPNOTSUPP, + ENOTTY, + ENOSYS); +} + +/* Two different errors for access problems */ +static inline bool ERRNO_IS_PRIVILEGE(int r) { + return IN_SET(abs(r), + EACCES, + EPERM); +} diff --git a/shared/systemd/src/basic/extract-word.c b/shared/systemd/src/basic/extract-word.c index 15cbaafb..2da25b03 100644 --- a/shared/systemd/src/basic/extract-word.c +++ b/shared/systemd/src/basic/extract-word.c @@ -8,7 +8,6 @@ #include <stddef.h> #include <stdint.h> #include <stdlib.h> -#include <string.h> #include <syslog.h> #include "alloc-util.h" @@ -30,8 +29,6 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra assert(p); assert(ret); - /* Those two don't make sense together. */ - assert(!FLAGS_SET(flags, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE)); /* Bail early if called after last value or with no input */ if (!*p) diff --git a/shared/systemd/src/basic/fd-util.c b/shared/systemd/src/basic/fd-util.c index 941053bf..ea2c1612 100644 --- a/shared/systemd/src/basic/fd-util.c +++ b/shared/systemd/src/basic/fd-util.c @@ -5,7 +5,6 @@ #include <errno.h> #include <fcntl.h> #include <sys/resource.h> -#include <sys/socket.h> #include <sys/stat.h> #include <unistd.h> @@ -18,7 +17,8 @@ #include "io-util.h" #include "macro.h" #include "memfd-util.h" -#include "missing.h" +#include "missing_fcntl.h" +#include "missing_syscall.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" diff --git a/shared/systemd/src/basic/fileio.c b/shared/systemd/src/basic/fileio.c index bd2afbbe..3bffa1c5 100644 --- a/shared/systemd/src/basic/fileio.c +++ b/shared/systemd/src/basic/fileio.c @@ -10,7 +10,6 @@ #include <stdint.h> #include <stdio_ext.h> #include <stdlib.h> -#include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -22,7 +21,6 @@ #include "hexdecoct.h" #include "log.h" #include "macro.h" -#include "missing.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" @@ -314,6 +312,113 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { } #endif /* NM_IGNORED */ +int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size) { + _cleanup_free_ char *buf = NULL; + _cleanup_close_ int fd = -1; + struct stat st; + size_t n, size; + int n_retries; + char *p; + + assert(ret_contents); + + /* Virtual filesystems such as sysfs or procfs use kernfs, and kernfs can work + * with two sorts of virtual files. One sort uses "seq_file", and the results of + * the first read are buffered for the second read. The other sort uses "raw" + * reads which always go direct to the device. In the latter case, the content of + * the virtual file must be retrieved with a single read otherwise a second read + * might get the new value instead of finding EOF immediately. That's the reason + * why the usage of fread(3) is prohibited in this case as it always performs a + * second call to read(2) looking for EOF. See issue 13585. */ + + fd = open(filename, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return -errno; + + /* Start size for files in /proc which usually report a file size of 0. */ + size = LINE_MAX / 2; + + /* Limit the number of attempts to read the number of bytes returned by fstat(). */ + n_retries = 3; + + for (;;) { + if (n_retries <= 0) + return -EIO; + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISREG(st.st_mode)) + return -EBADF; + + /* Be prepared for files from /proc which generally report a file size of 0. */ + if (st.st_size > 0) { + size = st.st_size; + n_retries--; + } else + size = size * 2; + + if (size > READ_FULL_BYTES_MAX) + return -E2BIG; + + p = realloc(buf, size + 1); + if (!p) + return -ENOMEM; + buf = TAKE_PTR(p); + + for (;;) { + ssize_t k; + + /* Read one more byte so we can detect whether the content of the + * file has already changed or the guessed size for files from /proc + * wasn't large enough . */ + k = read(fd, buf, size + 1); + if (k >= 0) { + n = k; + break; + } + + if (errno != -EINTR) + return -errno; + } + + /* Consider a short read as EOF */ + if (n <= size) + break; + + /* Hmm... either we read too few bytes from /proc or less likely the content + * of the file might have been changed (and is now bigger) while we were + * processing, let's try again either with a bigger guessed size or the new + * file size. */ + + if (lseek(fd, 0, SEEK_SET) < 0) + return -errno; + } + + if (n < size) { + p = realloc(buf, n + 1); + if (!p) + return -ENOMEM; + buf = TAKE_PTR(p); + } + + if (!ret_size) { + /* Safety check: if the caller doesn't want to know the size of what we + * just read it will rely on the trailing NUL byte. But if there's an + * embedded NUL byte, then we should refuse operation as otherwise + * there'd be ambiguity about what we just read. */ + + if (memchr(buf, 0, n)) + return -EBADMSG; + } else + *ret_size = n; + + buf[n] = 0; + *ret_contents = TAKE_PTR(buf); + + return 0; +} + int read_full_stream_full( FILE *f, const char *filename, @@ -346,9 +451,9 @@ int read_full_stream_full( if (st.st_size > READ_FULL_BYTES_MAX) return -E2BIG; - /* Start with the right file size, but be prepared for files from /proc which generally report a file - * size of 0. Note that we increase the size to read here by one, so that the first read attempt - * already makes us notice the EOF. */ + /* Start with the right file size. Note that we increase the size + * to read here by one, so that the first read attempt already + * makes us notice the EOF. */ if (st.st_size > 0) n_next = st.st_size + 1; @@ -508,7 +613,7 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin assert(pattern); assert(field); - r = read_full_file(filename, &status, NULL); + r = read_full_virtual_file(filename, &status, NULL); if (r < 0) return r; @@ -942,10 +1047,10 @@ int warn_file_is_world_accessible(const char *filename, struct stat *st, const c if (unit) log_syntax(unit, LOG_WARNING, filename, line, 0, - "%s has %04o mode that is too permissive, please adjust the access mode.", + "%s has %04o mode that is too permissive, please adjust the ownership and access mode.", filename, st->st_mode & 07777); else - log_warning("%s has %04o mode that is too permissive, please adjust the access mode.", + log_warning("%s has %04o mode that is too permissive, please adjust the ownership and access mode.", filename, st->st_mode & 07777); return 0; } diff --git a/shared/systemd/src/basic/fileio.h b/shared/systemd/src/basic/fileio.h index 05f6c89d..31bfef33 100644 --- a/shared/systemd/src/basic/fileio.h +++ b/shared/systemd/src/basic/fileio.h @@ -56,6 +56,7 @@ int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **co static inline int read_full_file(const char *filename, char **contents, size_t *size) { return read_full_file_full(filename, 0, contents, size); } +int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size); int read_full_stream_full(FILE *f, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size); static inline int read_full_stream(FILE *f, char **contents, size_t *size) { return read_full_stream_full(f, NULL, 0, contents, size); diff --git a/shared/systemd/src/basic/format-util.c b/shared/systemd/src/basic/format-util.c index 7a3e735b..62477f53 100644 --- a/shared/systemd/src/basic/format-util.c +++ b/shared/systemd/src/basic/format-util.c @@ -2,15 +2,26 @@ #include "nm-sd-adapt-shared.h" -#include <stdio.h> - #include "format-util.h" #include "memory-util.h" +#include "stdio-util.h" -char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]) { +assert_cc(DECIMAL_STR_MAX(int) + 1 <= IF_NAMESIZE + 1); +char *format_ifname_full(int ifindex, char buf[static IF_NAMESIZE + 1], FormatIfnameFlag flag) { /* Buffer is always cleared */ memzero(buf, IF_NAMESIZE + 1); - return if_indextoname(ifindex, buf); + if (if_indextoname(ifindex, buf)) + return buf; + + if (!FLAGS_SET(flag, FORMAT_IFNAME_IFINDEX)) + return NULL; + + if (FLAGS_SET(flag, FORMAT_IFNAME_IFINDEX_WITH_PERCENT)) + snprintf(buf, IF_NAMESIZE + 1, "%%%d", ifindex); + else + snprintf(buf, IF_NAMESIZE + 1, "%d", ifindex); + + return buf; } char *format_bytes_full(char *buf, size_t l, uint64_t t, FormatBytesFlag flag) { diff --git a/shared/systemd/src/basic/format-util.h b/shared/systemd/src/basic/format-util.h index e0d184a5..59622508 100644 --- a/shared/systemd/src/basic/format-util.h +++ b/shared/systemd/src/basic/format-util.h @@ -68,7 +68,15 @@ # error Unknown ino_t size #endif -char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]); +typedef enum { + FORMAT_IFNAME_IFINDEX = 1 << 0, + FORMAT_IFNAME_IFINDEX_WITH_PERCENT = (1 << 1) | FORMAT_IFNAME_IFINDEX, +} FormatIfnameFlag; + +char *format_ifname_full(int ifindex, char buf[static IF_NAMESIZE + 1], FormatIfnameFlag flag); +static inline char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]) { + return format_ifname_full(ifindex, buf, 0); +} typedef enum { FORMAT_BYTES_USE_IEC = 1 << 0, diff --git a/shared/systemd/src/basic/fs-util.c b/shared/systemd/src/basic/fs-util.c index 56385fa2..e30f40fb 100644 --- a/shared/systemd/src/basic/fs-util.c +++ b/shared/systemd/src/basic/fs-util.c @@ -4,13 +4,9 @@ #include <errno.h> #include <stddef.h> -#include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <sys/stat.h> #include <linux/falloc.h> #include <linux/magic.h> -#include <time.h> #include <unistd.h> #include "alloc-util.h" @@ -20,7 +16,9 @@ #include "locale-util.h" #include "log.h" #include "macro.h" -#include "missing.h" +#include "missing_fcntl.h" +#include "missing_fs.h" +#include "missing_syscall.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" @@ -669,6 +667,18 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) { } #if 0 /* NM_IGNORED */ +int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) { + + if (inotify_add_watch(fd, pathname, mask) < 0) { + if (errno == ENOSPC) + return log_error_errno(errno, "Failed to add a watch for %s: inotify watch limit reached", pathname); + + return log_error_errno(errno, "Failed to add a watch for %s: %m", pathname); + } + + return 0; +} + static bool unsafe_transition(const struct stat *a, const struct stat *b) { /* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to * privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files @@ -707,7 +717,7 @@ static int log_autofs_mount_point(int fd, const char *path, unsigned flags) { n1, path); } -int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) { +int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) { _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL; _cleanup_close_ int fd = -1; unsigned max_follow = CHASE_SYMLINKS_MAX; /* how many symlinks to follow before giving up and returning ELOOP */ @@ -719,10 +729,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, assert(path); /* Either the file may be missing, or we return an fd to the final object, but both make no sense */ - if (FLAGS_SET(flags, CHASE_NONEXISTENT | CHASE_OPEN)) + if ((flags & CHASE_NONEXISTENT) && ret_fd) return -EINVAL; - if (FLAGS_SET(flags, CHASE_STEP | CHASE_OPEN)) + if ((flags & CHASE_STEP) && ret_fd) return -EINVAL; if (isempty(path)) @@ -741,24 +751,24 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races - * at a minimum. + * to a minimum. * * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this * function what to do when encountering a symlink with an absolute path as directory: prefix it by the * specified path. * - * There are three ways to invoke this function: + * There are five ways to invoke this function: * - * 1. Without CHASE_STEP or CHASE_OPEN: in this case the path is resolved and the normalized path is returned - * in `ret`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set 0 is returned if the file - * doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set >= 0 is returned if the destination was - * found, -ENOENT if it doesn't. + * 1. Without CHASE_STEP or ret_fd: in this case the path is resolved and the normalized path is + * returned in `ret_path`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0 + * is returned if the file doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is + * returned if the destination was found, -ENOENT if it wasn't. * - * 2. With CHASE_OPEN: in this case the destination is opened after chasing it as O_PATH and this file + * 2. With ret_fd: in this case the destination is opened after chasing it as O_PATH and this file * descriptor is returned as return value. This is useful to open files relative to some root * directory. Note that the returned O_PATH file descriptors must be converted into a regular one (using - * fd_reopen() or such) before it can be used for reading/writing. CHASE_OPEN may not be combined with + * fd_reopen() or such) before it can be used for reading/writing. ret_fd may not be combined with * CHASE_NONEXISTENT. * * 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only the first @@ -769,26 +779,26 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, * * 4. With CHASE_SAFE: in this case the path must not contain unsafe transitions, i.e. transitions from * unprivileged to privileged files or directories. In such cases the return value is -ENOLINK. If - * CHASE_WARN is also set a warning describing the unsafe transition is emitted. + * CHASE_WARN is also set, a warning describing the unsafe transition is emitted. * - * 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, the path normalization is - * aborted and -EREMOTE is returned. If CHASE_WARN is also set a warning showing the path of the mount point - * is emitted. - * - * */ + * 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, path normalization + * is aborted and -EREMOTE is returned. If CHASE_WARN is also set, a warning showing the path of + * the mount point is emitted. + */ /* A root directory of "/" or "" is identical to none */ if (empty_or_root(original_root)) original_root = NULL; - if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) { - /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set + if (!original_root && !ret_path && !(flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_STEP)) && ret_fd) { + /* Shortcut the ret_fd case if the caller isn't interested in the actual path and has no root set * and doesn't care about any of the other special features we provide either. */ r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0)); if (r < 0) return -errno; - return r; + *ret_fd = r; + return 0; } if (original_root) { @@ -797,7 +807,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return r; if (flags & CHASE_PREFIX_ROOT) { - /* We don't support relative paths in combination with a root directory */ if (!path_is_absolute(path)) return -EINVAL; @@ -942,7 +951,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) { char *joined; - _cleanup_free_ char *destination = NULL; /* This is a symlink, in this case read the destination. But let's make sure we don't follow @@ -1028,15 +1036,15 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return -ENOMEM; } - if (ret) - *ret = TAKE_PTR(done); + if (ret_path) + *ret_path = TAKE_PTR(done); - if (flags & CHASE_OPEN) { - /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by - * opening /proc/self/fd/xyz. */ + if (ret_fd) { + /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a + * proper fd by opening /proc/self/fd/xyz. */ assert(fd >= 0); - return TAKE_FD(fd); + *ret_fd = TAKE_FD(fd); } if (flags & CHASE_STEP) @@ -1045,14 +1053,14 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return exists; chased_one: - if (ret) { + if (ret_path) { char *c; c = strjoin(strempty(done), todo); if (!c) return -ENOMEM; - *ret = c; + *ret_path = c; } return 0; @@ -1081,9 +1089,10 @@ int chase_symlinks_and_open( return r; } - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); r = fd_reopen(path_fd, open_flags); if (r < 0) @@ -1106,6 +1115,7 @@ int chase_symlinks_and_opendir( _cleanup_close_ int path_fd = -1; _cleanup_free_ char *p = NULL; DIR *d; + int r; if (!ret_dir) return -EINVAL; @@ -1122,9 +1132,10 @@ int chase_symlinks_and_opendir( return 0; } - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); xsprintf(procfs_path, "/proc/self/fd/%i", path_fd); d = opendir(procfs_path); @@ -1143,10 +1154,12 @@ int chase_symlinks_and_stat( const char *root, unsigned chase_flags, char **ret_path, - struct stat *ret_stat) { + struct stat *ret_stat, + int *ret_fd) { _cleanup_close_ int path_fd = -1; _cleanup_free_ char *p = NULL; + int r; assert(path); assert(ret_stat); @@ -1162,18 +1175,18 @@ int chase_symlinks_and_stat( return 1; } - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); if (fstat(path_fd, ret_stat) < 0) return -errno; if (ret_path) *ret_path = TAKE_PTR(p); - - if (chase_flags & CHASE_OPEN) - return TAKE_FD(path_fd); + if (ret_fd) + *ret_fd = TAKE_FD(path_fd); return 1; } @@ -1307,6 +1320,17 @@ int fsync_directory_of_file(int fd) { return 0; } +int fsync_full(int fd) { + int r, q; + + /* Sync both the file and the directory */ + + r = fsync(fd) < 0 ? -errno : 0; + q = fsync_directory_of_file(fd); + + return r < 0 ? r : q; +} + int fsync_path_at(int at_fd, const char *path) { _cleanup_close_ int opened_fd = -1; int fd; diff --git a/shared/systemd/src/basic/fs-util.h b/shared/systemd/src/basic/fs-util.h index c5527cc4..78d68be9 100644 --- a/shared/systemd/src/basic/fs-util.h +++ b/shared/systemd/src/basic/fs-util.h @@ -72,27 +72,28 @@ union inotify_event_buffer { }; int inotify_add_watch_fd(int fd, int what, uint32_t mask); +int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask); enum { - CHASE_PREFIX_ROOT = 1 << 0, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */ - CHASE_NONEXISTENT = 1 << 1, /* If set, it's OK if the path doesn't actually exist. */ - CHASE_NO_AUTOFS = 1 << 2, /* If set, return -EREMOTE if autofs mount point found */ - CHASE_SAFE = 1 << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */ - CHASE_OPEN = 1 << 4, /* If set, return an O_PATH object to the final component */ - CHASE_TRAIL_SLASH = 1 << 5, /* If set, any trailing slash will be preserved */ - CHASE_STEP = 1 << 6, /* If set, just execute a single step of the normalization */ - CHASE_NOFOLLOW = 1 << 7, /* Only valid with CHASE_OPEN: when the path's right-most component refers to symlink return O_PATH fd of the symlink, rather than following it. */ - CHASE_WARN = 1 << 8, /* Emit an appropriate warning when an error is encountered */ + CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */ + CHASE_NONEXISTENT = 1 << 1, /* It's OK if the path doesn't actually exist. */ + CHASE_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */ + CHASE_SAFE = 1 << 3, /* Return EPERM if we ever traverse from unprivileged to privileged files or directories */ + CHASE_TRAIL_SLASH = 1 << 4, /* Any trailing slash will be preserved */ + CHASE_STEP = 1 << 5, /* Just execute a single step of the normalization */ + CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most compontent. With ret_fd, when the path's + * right-most component refers to symlink, return O_PATH fd of the symlink. */ + CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered */ }; /* How many iterations to execute before returning -ELOOP */ #define CHASE_SYMLINKS_MAX 32 -int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret); +int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret_path, int *ret_fd); int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path); int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir); -int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat); +int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd); /* Useful for usage with _cleanup_(), removes a directory and frees the pointer */ static inline void rmdir_and_free(char *p) { @@ -114,6 +115,7 @@ void unlink_tempfilep(char (*p)[]); int unlinkat_deallocate(int fd, const char *name, int flags); int fsync_directory_of_file(int fd); +int fsync_full(int fd); int fsync_path_at(int at_fd, const char *path); int syncfs_path(int atfd, const char *path); diff --git a/shared/systemd/src/basic/hash-funcs.c b/shared/systemd/src/basic/hash-funcs.c index 03695098..1b0d1292 100644 --- a/shared/systemd/src/basic/hash-funcs.c +++ b/shared/systemd/src/basic/hash-funcs.c @@ -55,11 +55,7 @@ void path_hash_func(const char *q, struct siphash *state) { } } -int path_compare_func(const char *a, const char *b) { - return path_compare(a, b); -} - -DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare_func); +DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare); #endif /* NM_IGNORED */ void trivial_hash_func(const void *p, struct siphash *state) { diff --git a/shared/systemd/src/basic/hash-funcs.h b/shared/systemd/src/basic/hash-funcs.h index 0d2d4283..7bb5d1cd 100644 --- a/shared/systemd/src/basic/hash-funcs.h +++ b/shared/systemd/src/basic/hash-funcs.h @@ -79,7 +79,6 @@ extern const struct hash_ops string_hash_ops; extern const struct hash_ops string_hash_ops_free_free; void path_hash_func(const char *p, struct siphash *state); -int path_compare_func(const char *a, const char *b) _pure_; extern const struct hash_ops path_hash_ops; /* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings diff --git a/shared/systemd/src/basic/hashmap.c b/shared/systemd/src/basic/hashmap.c index b1ae08cd..1aa00947 100644 --- a/shared/systemd/src/basic/hashmap.c +++ b/shared/systemd/src/basic/hashmap.c @@ -5,7 +5,6 @@ #include <errno.h> #include <stdint.h> #include <stdlib.h> -#include <string.h> #include "alloc-util.h" #include "fileio.h" @@ -13,7 +12,7 @@ #include "macro.h" #include "memory-util.h" #include "mempool.h" -#include "missing.h" +#include "missing_syscall.h" #include "process-util.h" #include "random-util.h" #include "set.h" diff --git a/shared/systemd/src/basic/hostname-util.c b/shared/systemd/src/basic/hostname-util.c index 60a94b96..00a92cb7 100644 --- a/shared/systemd/src/basic/hostname-util.c +++ b/shared/systemd/src/basic/hostname-util.c @@ -5,7 +5,6 @@ #include <errno.h> #include <limits.h> #include <stdio.h> -#include <string.h> #include <sys/utsname.h> #include <unistd.h> diff --git a/shared/systemd/src/basic/io-util.c b/shared/systemd/src/basic/io-util.c index 9669c463..4f57f044 100644 --- a/shared/systemd/src/basic/io-util.c +++ b/shared/systemd/src/basic/io-util.c @@ -6,7 +6,6 @@ #include <limits.h> #include <poll.h> #include <stdio.h> -#include <time.h> #include <unistd.h> #include "io-util.h" diff --git a/shared/systemd/src/basic/macro.h b/shared/systemd/src/basic/macro.h index 43c51326..fc733366 100644 --- a/shared/systemd/src/basic/macro.h +++ b/shared/systemd/src/basic/macro.h @@ -316,17 +316,18 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { extern void __coverity_panic__(void); -static inline int __coverity_check__(int condition) { +static inline void __coverity_check__(int condition) { + if (!condition) + __coverity_panic__(); +} + +static inline int __coverity_check_and_return__(int condition) { return condition; } -#define assert_message_se(expr, message) \ - do { \ - if (__coverity_check__(!(expr))) \ - __coverity_panic__(); \ - } while (false) +#define assert_message_se(expr, message) __coverity_check__(!!(expr)) -#define assert_log(expr, message) __coverity_check__(!!(expr)) +#define assert_log(expr, message) __coverity_check_and_return__(!!(expr)) #else /* ! __COVERITY__ */ diff --git a/shared/systemd/src/basic/memory-util.h b/shared/systemd/src/basic/memory-util.h index 9cb8ac3c..46a6907a 100644 --- a/shared/systemd/src/basic/memory-util.h +++ b/shared/systemd/src/basic/memory-util.h @@ -11,6 +11,7 @@ size_t page_size(void) _pure_; #define PAGE_ALIGN(l) ALIGN_TO((l), page_size()) +#define PAGE_ALIGN_DOWN(l) (l & ~(page_size() - 1)) /* Normal memcpy requires src to be nonnull. We do nothing if n is 0. */ static inline void memcpy_safe(void *dst, const void *src, size_t n) { diff --git a/shared/systemd/src/basic/missing_random.h b/shared/systemd/src/basic/missing_random.h new file mode 100644 index 00000000..2e76031b --- /dev/null +++ b/shared/systemd/src/basic/missing_random.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if USE_SYS_RANDOM_H +# include <sys/random.h> +#else +# include <linux/random.h> +#endif + +#ifndef GRND_NONBLOCK +#define GRND_NONBLOCK 0x0001 +#endif + +#ifndef GRND_RANDOM +#define GRND_RANDOM 0x0002 +#endif diff --git a/shared/systemd/src/basic/parse-util.c b/shared/systemd/src/basic/parse-util.c index 76ef6e09..96cc43a2 100644 --- a/shared/systemd/src/basic/parse-util.c +++ b/shared/systemd/src/basic/parse-util.c @@ -5,11 +5,9 @@ #include <errno.h> #include <inttypes.h> #include <linux/oom.h> -#include <locale.h> #include <net/if.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/socket.h> #include "alloc-util.h" @@ -17,7 +15,7 @@ #include "extract-word.h" #include "locale-util.h" #include "macro.h" -#include "missing.h" +#include "missing_network.h" #include "parse-util.h" #include "process-util.h" #include "stat-util.h" diff --git a/shared/systemd/src/basic/path-util.c b/shared/systemd/src/basic/path-util.c index e39656bc..5bcc35e5 100644 --- a/shared/systemd/src/basic/path-util.c +++ b/shared/systemd/src/basic/path-util.c @@ -6,8 +6,6 @@ #include <limits.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <sys/stat.h> #include <unistd.h> /* When we include libgen.h because we need dirname() we immediately @@ -22,7 +20,6 @@ #include "glob-util.h" #include "log.h" #include "macro.h" -#include "missing.h" #include "nulstr-util.h" #include "parse-util.h" #include "path-util.h" @@ -276,7 +273,7 @@ char **path_strv_resolve(char **l, const char *root) { } else t = *s; - r = chase_symlinks(t, root, 0, &u); + r = chase_symlinks(t, root, 0, &u, NULL); if (r == -ENOENT) { if (root) { u = TAKE_PTR(orig); @@ -658,7 +655,9 @@ int find_binary(const char *name, char **ret) { return 0; } - last_error = -errno; + /* PATH entries which we don't have access to are ignored, as per tradition. */ + if (errno != EACCES) + last_error = -errno; } return last_error; diff --git a/shared/systemd/src/basic/path-util.h b/shared/systemd/src/basic/path-util.h index cd6216bb..88aef2f3 100644 --- a/shared/systemd/src/basic/path-util.h +++ b/shared/systemd/src/basic/path-util.h @@ -40,6 +40,10 @@ #endif #endif /* NM_IGNORED */ +#ifndef DEFAULT_USER_PATH +# define DEFAULT_USER_PATH DEFAULT_PATH +#endif + bool is_path(const char *p) _pure_; int path_split_and_make_absolute(const char *p, char ***ret); bool path_is_absolute(const char *p) _pure_; diff --git a/shared/systemd/src/basic/process-util.c b/shared/systemd/src/basic/process-util.c index 317815fe..14561670 100644 --- a/shared/systemd/src/basic/process-util.c +++ b/shared/systemd/src/basic/process-util.c @@ -6,11 +6,9 @@ #include <errno.h> #include <limits.h> #include <linux/oom.h> -#include <signal.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/mman.h> #include <sys/mount.h> #include <sys/personality.h> @@ -27,8 +25,8 @@ #include "alloc-util.h" #include "architecture.h" -#include "escape.h" #include "env-util.h" +#include "escape.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" @@ -37,8 +35,10 @@ #include "log.h" #include "macro.h" #include "memory-util.h" -#include "missing.h" +#include "missing_sched.h" +#include "missing_syscall.h" #include "namespace-util.h" +#include "path-util.h" #include "process-util.h" #include "raw-clone.h" #include "rlimit-util.h" @@ -58,13 +58,17 @@ #define COMM_MAX_LEN 128 static int get_process_state(pid_t pid) { + _cleanup_free_ char *line = NULL; const char *p; char state; int r; - _cleanup_free_ char *line = NULL; assert(pid >= 0); + /* Shortcut: if we are enquired about our own state, we are obviously running */ + if (pid == 0 || pid == getpid_cached()) + return (unsigned char) 'R'; + p = procfs_file_alloca(pid, "stat"); r = read_one_line_file(p, &line); @@ -87,24 +91,35 @@ static int get_process_state(pid_t pid) { int get_process_comm(pid_t pid, char **ret) { _cleanup_free_ char *escaped = NULL, *comm = NULL; - const char *p; int r; assert(ret); assert(pid >= 0); + if (pid == 0 || pid == getpid_cached()) { + comm = new0(char, TASK_COMM_LEN + 1); /* Must fit in 16 byte according to prctl(2) */ + if (!comm) + return -ENOMEM; + + if (prctl(PR_GET_NAME, comm) < 0) + return -errno; + } else { + const char *p; + + p = procfs_file_alloca(pid, "comm"); + + /* Note that process names of kernel threads can be much longer than TASK_COMM_LEN */ + r = read_one_line_file(p, &comm); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + } + escaped = new(char, COMM_MAX_LEN); if (!escaped) return -ENOMEM; - p = procfs_file_alloca(pid, "comm"); - - r = read_one_line_file(p, &comm); - if (r == -ENOENT) - return -ESRCH; - if (r < 0) - return r; - /* Escape unprintable characters, just in case, but don't grow the string beyond the underlying size */ cellescape(escaped, COMM_MAX_LEN, comm); @@ -507,6 +522,9 @@ int get_process_cwd(pid_t pid, char **cwd) { assert(pid >= 0); + if (pid == 0 || pid == getpid_cached()) + return safe_getcwd(cwd); + p = procfs_file_alloca(pid, "cwd"); return get_process_link_contents(p, cwd); diff --git a/shared/systemd/src/basic/process-util.h b/shared/systemd/src/basic/process-util.h index 20f663e2..66853c6e 100644 --- a/shared/systemd/src/basic/process-util.h +++ b/shared/systemd/src/basic/process-util.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include <alloca.h> #include <errno.h> #include <sched.h> #include <signal.h> diff --git a/shared/systemd/src/basic/random-util.c b/shared/systemd/src/basic/random-util.c index c70871bf..86917ca3 100644 --- a/shared/systemd/src/basic/random-util.c +++ b/shared/systemd/src/basic/random-util.c @@ -19,16 +19,13 @@ # include <sys/auxv.h> #endif -#if USE_SYS_RANDOM_H -# include <sys/random.h> -#else -# include <linux/random.h> -#endif - #include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "io-util.h" -#include "missing.h" +#include "missing_random.h" +#include "missing_syscall.h" +#include "parse-util.h" #include "random-util.h" #include "siphash24.h" #include "time-util.h" @@ -398,3 +395,28 @@ void random_bytes(void *p, size_t n) { /* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */ pseudo_random_bytes(p, n); } + +#if 0 /* NM_IGNORED */ +size_t random_pool_size(void) { + _cleanup_free_ char *s = NULL; + int r; + + /* Read pool size, if possible */ + r = read_one_line_file("/proc/sys/kernel/random/poolsize", &s); + if (r < 0) + log_debug_errno(r, "Failed to read pool size from kernel: %m"); + else { + unsigned sz; + + r = safe_atou(s, &sz); + if (r < 0) + log_debug_errno(r, "Failed to parse pool size: %s", s); + else + /* poolsize is in bits on 2.6, but we want bytes */ + return CLAMP(sz / 8, RANDOM_POOL_SIZE_MIN, RANDOM_POOL_SIZE_MAX); + } + + /* Use the minimum as default, if we can't retrieve the correct value */ + return RANDOM_POOL_SIZE_MIN; +} +#endif /* NM_IGNORED */ diff --git a/shared/systemd/src/basic/random-util.h b/shared/systemd/src/basic/random-util.h index 148b6c78..facc11b9 100644 --- a/shared/systemd/src/basic/random-util.h +++ b/shared/systemd/src/basic/random-util.h @@ -31,3 +31,9 @@ static inline uint32_t random_u32(void) { } int rdrand(unsigned long *ret); + +/* Some limits on the pool sizes when we deal with the kernel random pool */ +#define RANDOM_POOL_SIZE_MIN 512U +#define RANDOM_POOL_SIZE_MAX (10U*1024U*1024U) + +size_t random_pool_size(void); diff --git a/shared/systemd/src/basic/set.h b/shared/systemd/src/basic/set.h index 2bb26c68..5f195617 100644 --- a/shared/systemd/src/basic/set.h +++ b/shared/systemd/src/basic/set.h @@ -102,8 +102,8 @@ static inline void *set_steal_first(Set *s) { /* no set_steal_first_key */ /* no set_first_key */ -static inline void *set_first(Set *s) { - return internal_hashmap_first_key_and_value(HASHMAP_BASE(s), false, NULL); +static inline void *set_first(const Set *s) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE((Set *) s), false, NULL); } /* no set_next */ diff --git a/shared/systemd/src/basic/socket-util.c b/shared/systemd/src/basic/socket-util.c index b822ed03..cded4545 100644 --- a/shared/systemd/src/basic/socket-util.c +++ b/shared/systemd/src/basic/socket-util.c @@ -13,7 +13,7 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> +#include <sys/ioctl.h> #include <unistd.h> #include "alloc-util.h" @@ -25,7 +25,7 @@ #include "log.h" #include "macro.h" #include "memory-util.h" -#include "missing.h" +#include "missing_socket.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" diff --git a/shared/systemd/src/basic/stat-util.c b/shared/systemd/src/basic/stat-util.c index c9837fa1..071050f2 100644 --- a/shared/systemd/src/basic/stat-util.c +++ b/shared/systemd/src/basic/stat-util.c @@ -2,12 +2,9 @@ #include "nm-sd-adapt-shared.h" -#include <dirent.h> #include <errno.h> #include <fcntl.h> -#include <linux/magic.h> #include <sched.h> -#include <sys/stat.h> #include <sys/statvfs.h> #include <sys/types.h> #include <unistd.h> @@ -17,7 +14,8 @@ #include "fd-util.h" #include "fs-util.h" #include "macro.h" -#include "missing.h" +#include "missing_fs.h" +#include "missing_magic.h" #include "parse-util.h" #include "stat-util.h" #include "string-util.h" @@ -340,7 +338,7 @@ int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) { if (r < 0) return r; - return chase_symlinks(p, NULL, 0, ret); + return chase_symlinks(p, NULL, 0, ret, NULL); } int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno) { diff --git a/shared/systemd/src/basic/string-table.h b/shared/systemd/src/basic/string-table.h index 42fe4f43..2d3cf814 100644 --- a/shared/systemd/src/basic/string-table.h +++ b/shared/systemd/src/basic/string-table.h @@ -5,7 +5,6 @@ #include <errno.h> #include <stddef.h> #include <stdio.h> -#include <string.h> #include <sys/types.h> #include "macro.h" diff --git a/shared/systemd/src/basic/string-util.c b/shared/systemd/src/basic/string-util.c index 2d34603e..3d2feb18 100644 --- a/shared/systemd/src/basic/string-util.c +++ b/shared/systemd/src/basic/string-util.c @@ -7,7 +7,6 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "alloc-util.h" #include "escape.h" @@ -750,7 +749,7 @@ static void advance_offsets( } char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { - const char *i, *begin = NULL; + const char *begin = NULL; enum { STATE_OTHER, STATE_ESCAPE, @@ -758,7 +757,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { STATE_CSO, } state = STATE_OTHER; char *obuf = NULL; - size_t osz = 0, isz, shift[2] = {}; + size_t osz = 0, isz, shift[2] = {}, n_carriage_returns = 0; FILE *f; assert(ibuf); @@ -769,6 +768,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { * 1. Replaces TABs by 8 spaces * 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences * 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences + * 4. Strip trailing \r characters (since they would "move the cursor", but have no + * other effect). * * Everything else will be left as it is. In particular other ANSI sequences are left as they are, as * are any other special characters. Truncated ANSI sequences are left-as is too. This call is @@ -784,14 +785,24 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { if (!f) return NULL; - for (i = *ibuf; i < *ibuf + isz + 1; i++) { + for (const char *i = *ibuf; i < *ibuf + isz + 1; i++) { switch (state) { case STATE_OTHER: if (i >= *ibuf + isz) /* EOT */ break; - else if (*i == '\x1B') + + if (*i == '\r') { + n_carriage_returns++; + break; + } else if (*i == '\n') + /* Ignore carriage returns before new line */ + n_carriage_returns = 0; + for (; n_carriage_returns > 0; n_carriage_returns--) + fputc('\r', f); + + if (*i == '\x1B') state = STATE_ESCAPE; else if (*i == '\t') { fputs(" ", f); @@ -802,6 +813,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { break; case STATE_ESCAPE: + assert(n_carriage_returns == 0); + if (i >= *ibuf + isz) { /* EOT */ fputc('\x1B', f); advance_offsets(i - *ibuf, highlight, shift, 1); @@ -822,6 +835,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { break; case STATE_CSI: + assert(n_carriage_returns == 0); if (i >= *ibuf + isz || /* EOT … */ !strchr("01234567890;m", *i)) { /* … or invalid chars in sequence */ @@ -836,6 +850,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { break; case STATE_CSO: + assert(n_carriage_returns == 0); if (i >= *ibuf + isz || /* EOT … */ (*i != '\a' && (uint8_t) *i < 32U) || (uint8_t) *i > 126U) { /* … or invalid chars in sequence */ @@ -855,7 +870,6 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { fclose(f); return mfree(obuf); } - fclose(f); free_and_replace(*ibuf, obuf); diff --git a/shared/systemd/src/basic/string-util.h b/shared/systemd/src/basic/string-util.h index 76767afc..04cc82b3 100644 --- a/shared/systemd/src/basic/string-util.h +++ b/shared/systemd/src/basic/string-util.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include <alloca.h> #include <stdbool.h> #include <stddef.h> #include <string.h> @@ -45,6 +44,22 @@ static inline const char *strna(const char *s) { return s ?: "n/a"; } +static inline const char* yes_no(bool b) { + return b ? "yes" : "no"; +} + +static inline const char* true_false(bool b) { + return b ? "true" : "false"; +} + +static inline const char* one_zero(bool b) { + return b ? "1" : "0"; +} + +static inline const char* enable_disable(bool b) { + return b ? "enable" : "disable"; +} + static inline bool isempty(const char *p) { return !p || !p[0]; } diff --git a/shared/systemd/src/basic/strv.c b/shared/systemd/src/basic/strv.c index ba23178a..aa467132 100644 --- a/shared/systemd/src/basic/strv.c +++ b/shared/systemd/src/basic/strv.c @@ -7,7 +7,6 @@ #include <stdarg.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "alloc-util.h" #include "escape.h" diff --git a/shared/systemd/src/basic/strv.h b/shared/systemd/src/basic/strv.h index e80964ac..fbfa96a5 100644 --- a/shared/systemd/src/basic/strv.h +++ b/shared/systemd/src/basic/strv.h @@ -157,6 +157,18 @@ void strv_print(char **l); _found; \ }) +#define ENDSWITH_SET(p, ...) \ + ({ \ + const char *_p = (p); \ + char *_found = NULL, **_i; \ + STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \ + _found = endswith(_p, *_i); \ + if (_found) \ + break; \ + } \ + _found; \ + }) + #define FOREACH_STRING(x, y, ...) \ for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \ x; \ diff --git a/shared/systemd/src/basic/time-util.c b/shared/systemd/src/basic/time-util.c index aa790023..4411127a 100644 --- a/shared/systemd/src/basic/time-util.c +++ b/shared/systemd/src/basic/time-util.c @@ -6,9 +6,7 @@ #include <errno.h> #include <limits.h> #include <stdlib.h> -#include <string.h> #include <sys/mman.h> -#include <sys/stat.h> #include <sys/time.h> #include <sys/timerfd.h> #include <sys/timex.h> @@ -839,8 +837,12 @@ int parse_timestamp(const char *t, usec_t *usec) { } if (r == 0) { bool with_tz = true; + char *colon_tz; - if (setenv("TZ", tz, 1) != 0) { + /* tzset(3) says $TZ should be prefixed with ":" if we reference timezone files */ + colon_tz = strjoina(":", tz); + + if (setenv("TZ", colon_tz, 1) != 0) { shared->return_value = negative_errno(); _exit(EXIT_FAILURE); } @@ -1196,7 +1198,10 @@ bool ntp_synced(void) { if (adjtimex(&txc) < 0) return false; - if (txc.status & STA_UNSYNC) + /* Consider the system clock synchronized if the reported maximum error is smaller than the maximum + * value (16 seconds). Ignore the STA_UNSYNC flag as it may have been set to prevent the kernel from + * touching the RTC. */ + if (txc.maxerror >= 16000000) return false; return true; @@ -1262,6 +1267,7 @@ int get_timezones(char ***ret) { } strv_sort(zones); + strv_uniq(zones); } else if (errno != ENOENT) return -errno; @@ -1282,6 +1288,10 @@ bool timezone_is_valid(const char *name, int log_level) { if (isempty(name)) return false; + /* Always accept "UTC" as valid timezone, since it's the fallback, even if user has no timezones installed. */ + if (streq(name, "UTC")) + return true; + if (name[0] == '/') return false; @@ -1388,13 +1398,22 @@ bool clock_supported(clockid_t clock) { } #if 0 /* NM_IGNORED */ -int get_timezone(char **tz) { +int get_timezone(char **ret) { _cleanup_free_ char *t = NULL; const char *e; char *z; int r; r = readlink_malloc("/etc/localtime", &t); + if (r == -ENOENT) { + /* If the symlink does not exist, assume "UTC", like glibc does*/ + z = strdup("UTC"); + if (!z) + return -ENOMEM; + + *ret = z; + return 0; + } if (r < 0) return r; /* returns EINVAL if not a symlink */ @@ -1409,7 +1428,7 @@ int get_timezone(char **tz) { if (!z) return -ENOMEM; - *tz = z; + *ret = z; return 0; } @@ -1421,8 +1440,8 @@ struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc) { return utc ? gmtime_r(t, tm) : localtime_r(t, tm); } -unsigned long usec_to_jiffies(usec_t u) { - static thread_local unsigned long hz = 0; +static uint32_t sysconf_clock_ticks_cached(void) { + static thread_local uint32_t hz = 0; long r; if (hz == 0) { @@ -1432,7 +1451,17 @@ unsigned long usec_to_jiffies(usec_t u) { hz = r; } - return DIV_ROUND_UP(u , USEC_PER_SEC / hz); + return hz; +} + +uint32_t usec_to_jiffies(usec_t u) { + uint32_t hz = sysconf_clock_ticks_cached(); + return DIV_ROUND_UP(u, USEC_PER_SEC / hz); +} + +usec_t jiffies_to_usec(uint32_t j) { + uint32_t hz = sysconf_clock_ticks_cached(); + return DIV_ROUND_UP(j * USEC_PER_SEC, hz); } usec_t usec_shift_clock(usec_t x, clockid_t from, clockid_t to) { diff --git a/shared/systemd/src/basic/time-util.h b/shared/systemd/src/basic/time-util.h index e3a529d9..4c371257 100644 --- a/shared/systemd/src/basic/time-util.h +++ b/shared/systemd/src/basic/time-util.h @@ -136,7 +136,8 @@ int get_timezone(char **timezone); time_t mktime_or_timegm(struct tm *tm, bool utc); struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc); -unsigned long usec_to_jiffies(usec_t usec); +uint32_t usec_to_jiffies(usec_t usec); +usec_t jiffies_to_usec(uint32_t jiffies); bool in_utc_timezone(void); diff --git a/shared/systemd/src/basic/tmpfile-util.c b/shared/systemd/src/basic/tmpfile-util.c index c02ce3df..d8a689e0 100644 --- a/shared/systemd/src/basic/tmpfile-util.c +++ b/shared/systemd/src/basic/tmpfile-util.c @@ -2,7 +2,6 @@ #include "nm-sd-adapt-shared.h" -#include <stdio.h> #include <sys/mman.h> #include "alloc-util.h" diff --git a/shared/systemd/src/basic/utf8.c b/shared/systemd/src/basic/utf8.c index 3c51fa1f..ba28e129 100644 --- a/shared/systemd/src/basic/utf8.c +++ b/shared/systemd/src/basic/utf8.c @@ -28,7 +28,6 @@ #include <errno.h> #include <stdbool.h> #include <stdlib.h> -#include <string.h> #include "alloc-util.h" #include "gunicode.h" diff --git a/shared/systemd/src/basic/util.c b/shared/systemd/src/basic/util.c index 23aa6b26..8a3f95dc 100644 --- a/shared/systemd/src/basic/util.c +++ b/shared/systemd/src/basic/util.c @@ -2,50 +2,23 @@ #include "nm-sd-adapt-shared.h" -#include <alloca.h> #include <errno.h> #include <fcntl.h> -#include <sched.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #include <sys/mman.h> -#include <sys/prctl.h> -#include <sys/statfs.h> -#include <sys/sysmacros.h> -#include <sys/types.h> -#include <unistd.h> #include "alloc-util.h" -#include "btrfs-util.h" #include "build.h" -#include "def.h" -#include "device-nodes.h" #include "dirent-util.h" #include "env-file.h" #include "env-util.h" #include "fd-util.h" #include "fileio.h" -#include "format-util.h" -#include "hashmap.h" #include "hostname-util.h" #include "log.h" #include "macro.h" -#include "missing.h" #include "parse-util.h" -#include "path-util.h" -#include "process-util.h" -#include "procfs-util.h" -#include "set.h" -#include "signal-util.h" #include "stat-util.h" #include "string-util.h" -#include "strv.h" -#include "time-util.h" -#include "umask-util.h" -#include "user-util.h" #include "util.h" #include "virt.h" diff --git a/shared/systemd/src/basic/util.h b/shared/systemd/src/basic/util.h index 25e6ab81..6fc7480f 100644 --- a/shared/systemd/src/basic/util.h +++ b/shared/systemd/src/basic/util.h @@ -5,22 +5,6 @@ #include "macro.h" -static inline const char* yes_no(bool b) { - return b ? "yes" : "no"; -} - -static inline const char* true_false(bool b) { - return b ? "true" : "false"; -} - -static inline const char* one_zero(bool b) { - return b ? "1" : "0"; -} - -static inline const char* enable_disable(bool b) { - return b ? "enable" : "disable"; -} - extern int saved_argc; extern char **saved_argv; |