diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/fs-util.c | 29 | ||||
-rw-r--r-- | src/basic/fs-util.h | 2 | ||||
-rw-r--r-- | src/basic/strv.c | 18 | ||||
-rw-r--r-- | src/basic/strv.h | 4 | ||||
-rw-r--r-- | src/core/main.c | 15 | ||||
-rw-r--r-- | src/fstab-generator/fstab-generator.c | 42 | ||||
-rw-r--r-- | src/journal/journal-verify.c | 15 | ||||
-rw-r--r-- | src/journal/journalctl.c | 48 | ||||
-rw-r--r-- | src/libsystemd/libsystemd.sym | 5 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-match.c | 3 | ||||
-rw-r--r-- | src/libsystemd/sd-device/device-enumerator.c | 34 | ||||
-rw-r--r-- | src/libsystemd/sd-device/device-internal.h | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-device/sd-device.c | 127 | ||||
-rw-r--r-- | src/libsystemd/sd-event/sd-event.c | 14 | ||||
-rw-r--r-- | src/machine/machinectl.c | 121 | ||||
-rw-r--r-- | src/network/networkd-wait-online-manager.c | 8 | ||||
-rw-r--r-- | src/nspawn/nspawn-patch-uid.c | 9 | ||||
-rw-r--r-- | src/resolve/resolved-manager.c | 5 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 56 | ||||
-rw-r--r-- | src/systemd/sd-event.h | 1 | ||||
-rw-r--r-- | src/test/test-fs-util.c | 46 | ||||
-rw-r--r-- | src/test/test-path-util.c | 2 | ||||
-rw-r--r-- | src/test/test-strv.c | 11 |
23 files changed, 467 insertions, 150 deletions
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index e24e7036f7..f0c6f3265e 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -38,6 +38,7 @@ #include "mkdir.h" #include "parse-util.h" #include "path-util.h" +#include "stat-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" @@ -495,6 +496,34 @@ int get_files_in_directory(const char *path, char ***list) { return n; } +int var_tmp(char **ret) { + const char *tmp_dir = NULL; + const char *env_tmp_dir = NULL; + char *c = NULL; + int r; + + assert(ret); + + env_tmp_dir = getenv("TMPDIR"); + if (env_tmp_dir != NULL) { + r = is_dir(env_tmp_dir, true); + if (r < 0 && r != -ENOENT) + return r; + if (r > 0) + tmp_dir = env_tmp_dir; + } + + if (!tmp_dir) + tmp_dir = "/var/tmp"; + + c = strdup(tmp_dir); + if (!c) + return -ENOMEM; + *ret = c; + + return 0; +} + int inotify_add_watch_fd(int fd, int what, uint32_t mask) { char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; int r; diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 517b599d6f..075e5942b1 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -61,6 +61,8 @@ int mkfifo_atomic(const char *path, mode_t mode); int get_files_in_directory(const char *path, char ***list); +int var_tmp(char **ret); + #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1) #define FOREACH_INOTIFY_EVENT(e, buffer, sz) \ diff --git a/src/basic/strv.c b/src/basic/strv.c index 97a96e5762..53298268f4 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -139,16 +139,16 @@ char **strv_new_ap(const char *x, va_list ap) { va_list aq; /* As a special trick we ignore all listed strings that equal - * (const char*) -1. This is supposed to be used with the + * STRV_IGNORE. This is supposed to be used with the * STRV_IFNOTNULL() macro to include possibly NULL strings in * the string list. */ if (x) { - n = x == (const char*) -1 ? 0 : 1; + n = x == STRV_IGNORE ? 0 : 1; va_copy(aq, ap); while ((s = va_arg(aq, const char*))) { - if (s == (const char*) -1) + if (s == STRV_IGNORE) continue; n++; @@ -162,7 +162,7 @@ char **strv_new_ap(const char *x, va_list ap) { return NULL; if (x) { - if (x != (const char*) -1) { + if (x != STRV_IGNORE) { a[i] = strdup(x); if (!a[i]) goto fail; @@ -171,7 +171,7 @@ char **strv_new_ap(const char *x, va_list ap) { while ((s = va_arg(ap, const char*))) { - if (s == (const char*) -1) + if (s == STRV_IGNORE) continue; a[i] = strdup(s); @@ -804,11 +804,7 @@ char **strv_reverse(char **l) { return l; for (i = 0; i < n / 2; i++) { - char *t; - - t = l[i]; - l[i] = l[n-1-i]; - l[n-1-i] = t; + SWAP_TWO(l[i], l[n-1-i]); } return l; @@ -838,7 +834,7 @@ bool strv_fnmatch(char* const* patterns, const char *s, int flags) { char* const* p; STRV_FOREACH(p, patterns) - if (fnmatch(*p, s, 0) == 0) + if (fnmatch(*p, s, flags) == 0) return true; return false; diff --git a/src/basic/strv.h b/src/basic/strv.h index f61bbb5386..683ce83a2a 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -69,8 +69,10 @@ bool strv_equal(char **a, char **b); char **strv_new(const char *x, ...) _sentinel_; char **strv_new_ap(const char *x, va_list ap); +#define STRV_IGNORE ((const char *) -1) + static inline const char* STRV_IFNOTNULL(const char *x) { - return x ? x : (const char *) -1; + return x ? x : STRV_IGNORE; } static inline bool strv_isempty(char * const *l) { diff --git a/src/core/main.c b/src/core/main.c index 237c9c9ebe..3d74ef1adf 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1507,13 +1507,14 @@ int main(int argc, char *argv[]) { (void) write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0); } - /* We expect the environment to be set correctly if run inside a - * container. */ - if (arg_system && detect_container() <= 0) { - if (fixup_environment() < 0) { - error_message = "Failed to fix up PID1 environment"; - goto finish; - } + if (arg_system) { + /* We expect the environment to be set correctly + * if run inside a container. */ + if (detect_container() <= 0) + if (fixup_environment() < 0) { + error_message = "Failed to fix up PID1 environment"; + goto finish; + } /* Try to figure out if we can use colors with the console. No * need to do that for user instances since they never log diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 880dc1bd2a..5aeca7e2d5 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -417,8 +417,7 @@ static int parse_fstab(bool initrd) { if (errno == ENOENT) return 0; - log_error_errno(errno, "Failed to open %s: %m", fstab_path); - return -errno; + return log_error_errno(errno, "Failed to open %s: %m", fstab_path); } while ((me = getmntent(f))) { @@ -502,7 +501,7 @@ static int add_sysroot_mount(void) { return 0; } - if (streq(arg_root_what, "/dev/nfs")) { + if (path_equal(arg_root_what, "/dev/nfs")) { /* This is handled by the kernel or the initrd */ log_debug("Skipping root directory handling, as /dev/nfs was requested."); return 0; @@ -532,10 +531,10 @@ static int add_sysroot_mount(void) { "/sysroot", arg_root_fstype, opts, - is_device_path(what) ? 1 : 0, - false, - false, - false, + is_device_path(what) ? 1 : 0, /* passno */ + false, /* noauto off */ + false, /* nofail off */ + false, /* automount off */ SPECIAL_INITRD_ROOT_FS_TARGET, "/proc/cmdline"); } @@ -548,22 +547,20 @@ static int add_sysroot_usr_mount(void) { return 0; if (arg_root_what && !arg_usr_what) { + /* Copy over the root device, in case the /usr mount just differs in a mount option (consider btrfs subvolumes) */ arg_usr_what = strdup(arg_root_what); - if (!arg_usr_what) return log_oom(); } if (arg_root_fstype && !arg_usr_fstype) { arg_usr_fstype = strdup(arg_root_fstype); - if (!arg_usr_fstype) return log_oom(); } if (arg_root_options && !arg_usr_options) { arg_usr_options = strdup(arg_root_options); - if (!arg_usr_options) return log_oom(); } @@ -572,10 +569,8 @@ static int add_sysroot_usr_mount(void) { return 0; what = fstab_node_to_udev_node(arg_usr_what); - if (!path_is_absolute(what)) { - log_debug("Skipping entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype)); - return -1; - } + if (!what) + return log_oom(); if (!arg_usr_options) opts = arg_root_rw > 0 ? "rw" : "ro"; @@ -589,10 +584,10 @@ static int add_sysroot_usr_mount(void) { "/sysroot/usr", arg_usr_fstype, opts, - 1, - false, - false, - false, + is_device_path(what) ? 1 : 0, /* passno */ + false, /* noauto off */ + false, /* nofail off */ + false, /* automount off */ SPECIAL_INITRD_FS_TARGET, "/proc/cmdline"); } @@ -687,10 +682,15 @@ int main(int argc, char *argv[]) { /* Always honour root= and usr= in the kernel command line if we are in an initrd */ if (in_initrd()) { + int k; + r = add_sysroot_mount(); - if (r == 0) - r = add_sysroot_usr_mount(); - } + + k = add_sysroot_usr_mount(); + if (k < 0) + r = k; + } else + r = 0; /* Honour /etc/fstab only when that's enabled */ if (arg_fstab_enabled) { diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index a37316b8f9..f61f158e8a 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -26,6 +26,7 @@ #include "compress.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "journal-authenticate.h" #include "journal-def.h" #include "journal-file.h" @@ -825,6 +826,8 @@ int journal_file_verify( int data_fd = -1, entry_fd = -1, entry_array_fd = -1; unsigned i; bool found_last = false; + _cleanup_free_ char *tmp_dir = NULL; + #ifdef HAVE_GCRYPT uint64_t last_tag = 0; #endif @@ -843,19 +846,25 @@ int journal_file_verify( } else if (f->seal) return -ENOKEY; - data_fd = open_tmpfile_unlinkable("/var/tmp", O_RDWR | O_CLOEXEC); + r = var_tmp(&tmp_dir); + if (r < 0) { + log_error_errno(r, "Failed to determine temporary directory: %m"); + goto fail; + } + + data_fd = open_tmpfile_unlinkable(tmp_dir, O_RDWR | O_CLOEXEC); if (data_fd < 0) { r = log_error_errno(data_fd, "Failed to create data file: %m"); goto fail; } - entry_fd = open_tmpfile_unlinkable("/var/tmp", O_RDWR | O_CLOEXEC); + entry_fd = open_tmpfile_unlinkable(tmp_dir, O_RDWR | O_CLOEXEC); if (entry_fd < 0) { r = log_error_errno(entry_fd, "Failed to create entry file: %m"); goto fail; } - entry_array_fd = open_tmpfile_unlinkable("/var/tmp", O_RDWR | O_CLOEXEC); + entry_array_fd = open_tmpfile_unlinkable(tmp_dir, O_RDWR | O_CLOEXEC); if (entry_array_fd < 0) { r = log_error_errno(entry_array_fd, "Failed to create entry array file: %m"); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 8e4897831b..4cc0c2b6c2 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -348,6 +348,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_NO_FULL, ARG_NO_TAIL, ARG_NEW_ID128, + ARG_THIS_BOOT, ARG_LIST_BOOTS, ARG_USER, ARG_SYSTEM, @@ -392,9 +393,9 @@ static int parse_argv(int argc, char *argv[]) { { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, { "quiet", no_argument, NULL, 'q' }, { "merge", no_argument, NULL, 'm' }, + { "this-boot", no_argument, NULL, ARG_THIS_BOOT }, /* deprecated */ { "boot", optional_argument, NULL, 'b' }, { "list-boots", no_argument, NULL, ARG_LIST_BOOTS }, - { "this-boot", optional_argument, NULL, 'b' }, /* deprecated */ { "dmesg", no_argument, NULL, 'k' }, { "system", no_argument, NULL, ARG_SYSTEM }, { "user", no_argument, NULL, ARG_USER }, @@ -544,6 +545,10 @@ static int parse_argv(int argc, char *argv[]) { arg_merge = true; break; + case ARG_THIS_BOOT: + arg_boot = true; + break; + case 'b': arg_boot = true; @@ -868,8 +873,8 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } - if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && (arg_file || arg_directory || arg_merge)) { - log_error("Using --boot or --list-boots with --file, --directory or --merge is not supported."); + if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && arg_merge) { + log_error("Using --boot or --list-boots with --merge is not supported."); return -EINVAL; } @@ -1102,13 +1107,13 @@ static int discover_next_boot(sd_journal *j, static int get_boots( sd_journal *j, BootId **boots, - sd_id128_t *query_ref_boot, - int ref_boot_offset) { + sd_id128_t *boot_id, + int offset) { bool skip_once; int r, count = 0; BootId *head = NULL, *tail = NULL; - const bool advance_older = query_ref_boot && ref_boot_offset <= 0; + const bool advance_older = boot_id && offset <= 0; sd_id128_t previous_boot_id; assert(j); @@ -1116,19 +1121,19 @@ static int get_boots( /* Adjust for the asymmetry that offset 0 is * the last (and current) boot, while 1 is considered the * (chronological) first boot in the journal. */ - skip_once = query_ref_boot && sd_id128_is_null(*query_ref_boot) && ref_boot_offset < 0; + skip_once = boot_id && sd_id128_is_null(*boot_id) && offset <= 0; /* Advance to the earliest/latest occurrence of our reference * boot ID (taking our lookup direction into account), so that * discover_next_boot() can do its job. * If no reference is given, the journal head/tail will do, * they're "virtual" boots after all. */ - if (query_ref_boot && !sd_id128_is_null(*query_ref_boot)) { + if (boot_id && !sd_id128_is_null(*boot_id)) { char match[9+32+1] = "_BOOT_ID="; sd_journal_flush_matches(j); - sd_id128_to_string(*query_ref_boot, match + 9); + sd_id128_to_string(*boot_id, match + 9); r = sd_journal_add_match(j, match, sizeof(match) - 1); if (r < 0) return r; @@ -1148,7 +1153,7 @@ static int get_boots( return r; else if (r == 0) goto finish; - else if (ref_boot_offset == 0) { + else if (offset == 0) { count = 1; goto finish; } @@ -1187,14 +1192,14 @@ static int get_boots( previous_boot_id = current->id; - if (query_ref_boot) { + if (boot_id) { if (!skip_once) - ref_boot_offset += advance_older ? 1 : -1; + offset += advance_older ? 1 : -1; skip_once = false; - if (ref_boot_offset == 0) { + if (offset == 0) { count = 1; - *query_ref_boot = current->id; + *boot_id = current->id; break; } } else { @@ -1250,7 +1255,7 @@ static int list_boots(sd_journal *j) { static int add_boot(sd_journal *j) { char match[9+32+1] = "_BOOT_ID="; - sd_id128_t ref_boot_id; + sd_id128_t boot_id; int r; assert(j); @@ -1258,11 +1263,16 @@ static int add_boot(sd_journal *j) { if (!arg_boot) return 0; - if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL)) + /* Take a shortcut and use the current boot_id, which we can do very quickly. + * We can do this only when we logs are coming from the current machine, + * so take the slow path if log location is specified. */ + if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL) && + !arg_directory && !arg_file) + return add_match_this_boot(j, arg_machine); - ref_boot_id = arg_boot_id; - r = get_boots(j, NULL, &ref_boot_id, arg_boot_offset); + boot_id = arg_boot_id; + r = get_boots(j, NULL, &boot_id, arg_boot_offset); assert(r <= 1); if (r <= 0) { const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r); @@ -1277,7 +1287,7 @@ static int add_boot(sd_journal *j) { return r == 0 ? -ENODATA : r; } - sd_id128_to_string(ref_boot_id, match + 9); + sd_id128_to_string(boot_id, match + 9); r = sd_journal_add_match(j, match, sizeof(match) - 1); if (r < 0) diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 0b3a1708dc..542254295c 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -495,3 +495,8 @@ global: sd_journal_open_directory_fd; sd_journal_open_files_fd; } LIBSYSTEMD_229; + +LIBSYSTEMD_231 { +global: + sd_event_get_iteration; +} LIBSYSTEMD_230; diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c index 397baf6f33..db01f21135 100644 --- a/src/libsystemd/sd-bus/bus-match.c +++ b/src/libsystemd/sd-bus/bus-match.c @@ -429,6 +429,9 @@ int bus_match_run( r = bus_match_run(bus, c, m); if (r != 0) return r; + + if (bus && bus->match_callbacks_modified) + return 0; } } diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index 4a7a8b1f9e..62d03ae00d 100644 --- a/src/libsystemd/sd-device/device-enumerator.c +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -696,17 +696,19 @@ static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const c static int enumerator_scan_devices_tags(sd_device_enumerator *enumerator) { const char *tag; Iterator i; - int r; + int r = 0; assert(enumerator); SET_FOREACH(tag, enumerator->match_tag, i) { - r = enumerator_scan_devices_tag(enumerator, tag); - if (r < 0) - return r; + int k; + + k = enumerator_scan_devices_tag(enumerator, tag); + if (k < 0) + r = k; } - return 0; + return r; } static int parent_add_child(sd_device_enumerator *enumerator, const char *path) { @@ -838,7 +840,7 @@ static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) { int device_enumerator_scan_devices(sd_device_enumerator *enumerator) { sd_device *device; - int r; + int r = 0, k; assert(enumerator); @@ -850,22 +852,22 @@ int device_enumerator_scan_devices(sd_device_enumerator *enumerator) { sd_device_unref(device); if (!set_isempty(enumerator->match_tag)) { - r = enumerator_scan_devices_tags(enumerator); - if (r < 0) - return r; + k = enumerator_scan_devices_tags(enumerator); + if (k < 0) + r = k; } else if (enumerator->match_parent) { - r = enumerator_scan_devices_children(enumerator); - if (r < 0) - return r; + k = enumerator_scan_devices_children(enumerator); + if (k < 0) + r = k; } else { - r = enumerator_scan_devices_all(enumerator); - if (r < 0) - return r; + k = enumerator_scan_devices_all(enumerator); + if (k < 0) + r = k; } enumerator->scan_uptodate = true; - return 0; + return r; } _public_ sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator) { diff --git a/src/libsystemd/sd-device/device-internal.h b/src/libsystemd/sd-device/device-internal.h index ab222e27de..9fad388953 100644 --- a/src/libsystemd/sd-device/device-internal.h +++ b/src/libsystemd/sd-device/device-internal.h @@ -76,6 +76,8 @@ struct sd_device { char *subsystem; bool subsystem_set; /* don't reread subsystem */ + char *driver_subsystem; /* only set for the 'drivers' subsystem */ + bool driver_subsystem_set; /* don't reread subsystem */ char *driver; bool driver_set; /* don't reread driver */ diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 5c9e00ed80..d503232505 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -75,6 +75,7 @@ _public_ sd_device *sd_device_unref(sd_device *device) { free(device->devtype); free(device->devname); free(device->subsystem); + free(device->driver_subsystem); free(device->driver); free(device->id_filename); free(device->properties_strv); @@ -258,7 +259,8 @@ _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum) } _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname) { - char *syspath; + char *name, *syspath; + size_t len = 0; assert_return(ret, -EINVAL); assert_return(subsystem, -EINVAL); @@ -297,33 +299,29 @@ _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *s syspath = strjoina("/sys/bus/", subsys, "/drivers/", driver); if (access(syspath, F_OK) >= 0) return sd_device_new_from_syspath(ret, syspath); - } else - return -EINVAL; - } else { - char *name; - size_t len = 0; + } + } - /* translate sysname back to sysfs filename */ - name = strdupa(sysname); - while (name[len] != '\0') { - if (name[len] == '/') - name[len] = '!'; + /* translate sysname back to sysfs filename */ + name = strdupa(sysname); + while (name[len] != '\0') { + if (name[len] == '/') + name[len] = '!'; - len++; - } + len++; + } - syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", name); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); + syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", name); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); - syspath = strjoina("/sys/bus/", subsystem, "/devices/", name); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); + syspath = strjoina("/sys/bus/", subsystem, "/devices/", name); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); - syspath = strjoina("/sys/class/", subsystem, "/", name); - if (access(syspath, F_OK) >= 0) - return sd_device_new_from_syspath(ret, syspath); - } + syspath = strjoina("/sys/class/", subsystem, "/", name); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); return -ENODEV; } @@ -766,21 +764,45 @@ int device_set_subsystem(sd_device *device, const char *_subsystem) { return 0; } +static int device_set_drivers_subsystem(sd_device *device, const char *_subsystem) { + _cleanup_free_ char *subsystem = NULL; + int r; + + assert(device); + assert(_subsystem); + assert(*_subsystem); + + subsystem = strdup(_subsystem); + if (!subsystem) + return -ENOMEM; + + r = device_set_subsystem(device, "drivers"); + if (r < 0) + return r; + + free(device->driver_subsystem); + device->driver_subsystem = subsystem; + subsystem = NULL; + + return 0; +} + _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) { + const char *syspath, *drivers = NULL; + int r; + assert_return(ret, -EINVAL); assert_return(device, -EINVAL); + r = sd_device_get_syspath(device, &syspath); + if (r < 0) + return r; + if (!device->subsystem_set) { _cleanup_free_ char *subsystem = NULL; - const char *syspath; char *path; - int r; /* read 'subsystem' link */ - r = sd_device_get_syspath(device, &syspath); - if (r < 0) - return r; - path = strjoina(syspath, "/subsystem"); r = readlink_value(path, &subsystem); if (r >= 0) @@ -788,16 +810,39 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) { /* use implicit names */ else if (path_startswith(device->devpath, "/module/")) r = device_set_subsystem(device, "module"); - else if (strstr(device->devpath, "/drivers/")) - r = device_set_subsystem(device, "drivers"); - else if (path_startswith(device->devpath, "/subsystem/") || - path_startswith(device->devpath, "/class/") || - path_startswith(device->devpath, "/bus/")) + else if (!(drivers = strstr(syspath, "/drivers/")) && + (path_startswith(device->devpath, "/subsystem/") || + path_startswith(device->devpath, "/class/") || + path_startswith(device->devpath, "/bus/"))) r = device_set_subsystem(device, "subsystem"); if (r < 0 && r != -ENOENT) return log_debug_errno(r, "sd-device: could not set subsystem for %s: %m", device->devpath); device->subsystem_set = true; + } else if (!device->driver_subsystem_set) + drivers = strstr(syspath, "/drivers/"); + + if (!device->driver_subsystem_set) { + if (drivers) { + _cleanup_free_ char *subpath = NULL; + + subpath = strndup(syspath, drivers - syspath); + if (!subpath) + r = -ENOMEM; + else { + const char *subsys; + + subsys = strrchr(subpath, '/'); + if (!subsys) + r = -EINVAL; + else + r = device_set_drivers_subsystem(device, subsys + 1); + } + if (r < 0 && r != -ENOENT) + return log_debug_errno(r, "sd-device: could not set subsystem for driver %s: %m", device->devpath); + } + + device->driver_subsystem_set = true; } if (!device->subsystem) @@ -1234,9 +1279,17 @@ int device_get_id_filename(sd_device *device, const char **ret) { if (!subsystem) return -EINVAL; - r = asprintf(&id, "+%s:%s", subsystem, sysname); - if (r < 0) - return -ENOMEM; + if (streq(subsystem, "drivers")) { + /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem + * encoded as well */ + r = asprintf(&id, "+drivers:%s:%s", device->driver_subsystem, sysname); + if (r < 0) + return -ENOMEM; + } else { + r = asprintf(&id, "+%s:%s", subsystem, sysname); + if (r < 0) + return -ENOMEM; + } } device->id_filename = id; diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index f364b54b50..9857f8b1fc 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -109,8 +109,8 @@ struct sd_event_source { int64_t priority; unsigned pending_index; unsigned prepare_index; - unsigned pending_iteration; - unsigned prepare_iteration; + uint64_t pending_iteration; + uint64_t prepare_iteration; LIST_FIELDS(sd_event_source, sources); @@ -215,7 +215,7 @@ struct sd_event { pid_t original_pid; - unsigned iteration; + uint64_t iteration; triple_timestamp timestamp; int state; @@ -2874,3 +2874,11 @@ _public_ int sd_event_get_watchdog(sd_event *e) { return e->watchdog; } + +_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) { + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + *ret = e->iteration; + return 0; +} diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index d68c50b203..161dd3922b 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -32,6 +32,7 @@ #include "sd-bus.h" #include "alloc-util.h" +#include "bus-common-errors.h" #include "bus-error.h" #include "bus-unit-util.h" #include "bus-util.h" @@ -1523,6 +1524,32 @@ static int read_only_image(int argc, char *argv[], void *userdata) { return 0; } +static int image_exists(sd_bus *bus, const char *name) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + assert(name); + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetImage", + &error, + NULL, + "s", name); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_IMAGE)) + return 0; + + return log_error_errno(r, "Failed to check whether image %s exists: %s", name, bus_error_message(&error, -r)); + } + + return 1; +} + static int make_service_name(const char *name, char **ret) { _cleanup_free_ char *e = NULL; int r; @@ -1565,6 +1592,14 @@ static int start_machine(int argc, char *argv[], void *userdata) { if (r < 0) return r; + r = image_exists(bus, argv[i]); + if (r < 0) + return r; + if (r == 0) { + log_error("Machine image '%s' does not exist.", argv[1]); + return -ENXIO; + } + r = sd_bus_call_method( bus, "org.freedesktop.systemd1", @@ -1632,6 +1667,14 @@ static int enable_machine(int argc, char *argv[], void *userdata) { if (r < 0) return r; + r = image_exists(bus, argv[i]); + if (r < 0) + return r; + if (r == 0) { + log_error("Machine image '%s' does not exist.", argv[1]); + return -ENXIO; + } + r = sd_bus_message_append(m, "s", unit); if (r < 0) return bus_log_create_error(r); @@ -2543,35 +2586,65 @@ static int parse_argv(int argc, char *argv[]) { }; bool reorder = false; - int c, r; + int c, r, shell = -1; assert(argc >= 0); assert(argv); for (;;) { - const char * const option_string = "+hp:als:H:M:qn:o:"; + static const char option_string[] = "-hp:als:H:M:qn:o:"; c = getopt_long(argc, argv, option_string + reorder, options, NULL); - if (c < 0) { + if (c < 0) + break; + + switch (c) { + + case 1: /* getopt_long() returns 1 if "-" was the first character of the option string, and a + * non-option argument was discovered. */ + + assert(!reorder); + /* We generally are fine with the fact that getopt_long() reorders the command line, and looks * for switches after the main verb. However, for "shell" we really don't want that, since we - * want that switches passed after that are passed to the program to execute, and not processed - * by us. To make this possible, we'll first invoke getopt_long() with reordering disabled - * (i.e. with the "+" prefix in the option string), and as soon as we hit the end (i.e. the - * verb) we check if that's "shell". If it is, we exit the loop, since we don't want any - * further options processed. However, if it is anything else, we process the same argument - * again, but this time allow reordering. */ - - if (!reorder && optind < argc && !streq(argv[optind], "shell")) { + * want that switches specified after the machine name are passed to the program to execute, + * and not processed by us. To make this possible, we'll first invoke getopt_long() with + * reordering disabled (i.e. with the "-" prefix in the option string), looking for the first + * non-option parameter. If it's the verb "shell" we remember its position and continue + * processing options. In this case, as soon as we hit the next non-option argument we found + * the machine name, and stop further processing. If the first non-option argument is any other + * verb than "shell" we switch to normal reordering mode and continue processing arguments + * normally. */ + + if (shell >= 0) { + /* If we already found the "shell" verb on the command line, and now found the next + * non-option argument, then this is the machine name and we should stop processing + * further arguments. */ + optind --; /* don't process this argument, go one step back */ + goto done; + } + if (streq(optarg, "shell")) + /* Remember the position of the "shell" verb, and continue processing normally. */ + shell = optind - 1; + else { + int saved_optind; + + /* OK, this is some other verb. In this case, turn on reordering again, and continue + * processing normally. */ reorder = true; - optind--; - continue; + + /* We changed the option string. getopt_long() only looks at it again if we invoke it + * at least once with a reset option index. Hence, let's reset the option index here, + * then invoke getopt_long() again (ignoring what it has to say, after all we most + * likely already processed it), and the bump the option index so that we read the + * intended argument again. */ + saved_optind = optind; + optind = 0; + (void) getopt_long(argc, argv, option_string + reorder, options, NULL); + optind = saved_optind - 1; /* go one step back, process this argument again */ } break; - } - - switch (c) { case 'h': return help(0, NULL, NULL); @@ -2707,6 +2780,22 @@ static int parse_argv(int argc, char *argv[]) { } } +done: + if (shell >= 0) { + char *t; + int i; + + /* We found the "shell" verb while processing the argument list. Since we turned off reordering of the + * argument list initially let's readjust it now, and move the "shell" verb to the back. */ + + optind -= 1; /* place the option index where the "shell" verb will be placed */ + + t = argv[shell]; + for (i = shell; i < optind; i++) + argv[i] = argv[i+1]; + argv[optind] = t; + } + return 1; } diff --git a/src/network/networkd-wait-online-manager.c b/src/network/networkd-wait-online-manager.c index 2ff7ddb044..725b3310dd 100644 --- a/src/network/networkd-wait-online-manager.c +++ b/src/network/networkd-wait-online-manager.c @@ -30,8 +30,6 @@ #include "util.h" bool manager_ignore_link(Manager *m, Link *link) { - char **ignore; - assert(m); assert(link); @@ -44,11 +42,7 @@ bool manager_ignore_link(Manager *m, Link *link) { return true; /* ignore interfaces we explicitly are asked to ignore */ - STRV_FOREACH(ignore, m->ignore) - if (fnmatch(*ignore, link->ifname, 0) == 0) - return true; - - return false; + return strv_fnmatch(m->ignore, link->ifname, 0); } bool manager_all_configured(Manager *m) { diff --git a/src/nspawn/nspawn-patch-uid.c b/src/nspawn/nspawn-patch-uid.c index cc79597c95..ded5866d05 100644 --- a/src/nspawn/nspawn-patch-uid.c +++ b/src/nspawn/nspawn-patch-uid.c @@ -263,9 +263,12 @@ static int patch_fd(int fd, const char *name, const struct stat *st, uid_t shift return -errno; /* The Linux kernel alters the mode in some cases of chown(). Let's undo this. */ - if (name && !S_ISLNK(st->st_mode)) - r = fchmodat(fd, name, st->st_mode, 0); - else + if (name) { + if (!S_ISLNK(st->st_mode)) + r = fchmodat(fd, name, st->st_mode, 0); + else /* AT_SYMLINK_NOFOLLOW is not available for fchmodat() */ + r = 0; + } else r = fchmod(fd, st->st_mode); if (r < 0) return -errno; diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index add463b6a9..92ade820ac 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -1200,6 +1200,11 @@ int manager_compile_dns_servers(Manager *m, OrderedSet **dns) { return 0; } +/* filter_route is a tri-state: + * < 0: no filtering + * = 0 or false: return only domains which should be used for searching + * > 0 or true: return only domains which are for routing only + */ int manager_compile_search_domains(Manager *m, OrderedSet **domains, int filter_route) { DnsSearchDomain *d; Iterator i; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 0a8e60c195..b575437bcb 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -4367,7 +4367,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0) - print_prop("EnvironmentFile", "%s (ignore_errors=%s)\n", path, yes_no(ignore)); + print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path, yes_no(ignore)); if (r < 0) return bus_log_parse_error(r); @@ -5605,6 +5605,46 @@ static int mangle_names(char **original_names, char ***mangled_names) { return 0; } +static int unit_exists(const char *unit) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + static const struct bus_properties_map property_map[] = { + { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) }, + { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state)}, + {}, + }; + UnitStatusInfo info = {}; + sd_bus *bus; + int r; + + path = unit_dbus_path_from_name(unit); + if (!path) + return log_oom(); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.DBus.Properties", + "GetAll", + &error, + &reply, + "s", ""); + if (r < 0) + return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r)); + + r = bus_message_map_all_properties(reply, property_map, &info); + if (r < 0) + return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r)); + + return !streq_ptr(info.load_state, "not-found") || !streq_ptr(info.active_state, "inactive"); +} + static int enable_unit(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; const char *verb = argv[0]; @@ -5666,6 +5706,14 @@ static int enable_unit(int argc, char *argv[], void *userdata) { const char *method; sd_bus *bus; + if (STR_IN_SET(verb, "mask", "unmask")) { + r = unit_exists(*names); + if (r < 0) + return r; + if (r == 0) + log_notice("Unit %s does not exist, proceeding anyway.", *names); + } + r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; @@ -6175,7 +6223,7 @@ static int unit_file_create_copy( if (response != 'y') { log_warning("%s ignored", unit_name); free(tmp_new_path); - return -1; + return -EKEYREJECTED; } } @@ -6307,10 +6355,8 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { r = unit_file_create_copy(&lp, *name, path, &new_path, &tmp_path); else r = unit_file_create_new(&lp, *name, ".d/override.conf", &new_path, &tmp_path); - } else { + } else r = unit_file_create_new(&lp, *name, NULL, &new_path, &tmp_path); - } - if (r < 0) return r; diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h index 531ace1c34..cc26b7df55 100644 --- a/src/systemd/sd-event.h +++ b/src/systemd/sd-event.h @@ -104,6 +104,7 @@ int sd_event_get_tid(sd_event *e, pid_t *tid); int sd_event_get_exit_code(sd_event *e, int *code); int sd_event_set_watchdog(sd_event *e, int b); int sd_event_get_watchdog(sd_event *e); +int sd_event_get_iteration(sd_event *e, uint64_t *ret); sd_event_source* sd_event_source_ref(sd_event_source *s); sd_event_source* sd_event_source_unref(sd_event_source *s); diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 6db2c2b6f1..e0c040f39b 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -82,10 +82,56 @@ static void test_get_files_in_directory(void) { assert_se(get_files_in_directory(".", NULL) >= 0); } +static void test_var_tmp(void) { + char *tmp_dir = NULL; + char *tmpdir_backup = NULL; + const char *default_var_tmp = NULL; + const char *var_name; + bool do_overwrite = true; + + default_var_tmp = "/var/tmp"; + var_name = "TMPDIR"; + + if (getenv(var_name) != NULL) { + tmpdir_backup = strdup(getenv(var_name)); + assert_se(tmpdir_backup != NULL); + } + + unsetenv(var_name); + + var_tmp(&tmp_dir); + assert_se(!strcmp(tmp_dir, default_var_tmp)); + + free(tmp_dir); + + setenv(var_name, "/tmp", do_overwrite); + assert_se(!strcmp(getenv(var_name), "/tmp")); + + var_tmp(&tmp_dir); + assert_se(!strcmp(tmp_dir, "/tmp")); + + free(tmp_dir); + + setenv(var_name, "/88_does_not_exist_88", do_overwrite); + assert_se(!strcmp(getenv(var_name), "/88_does_not_exist_88")); + + var_tmp(&tmp_dir); + assert_se(!strcmp(tmp_dir, default_var_tmp)); + + free(tmp_dir); + + if (tmpdir_backup != NULL) { + setenv(var_name, tmpdir_backup, do_overwrite); + assert_se(!strcmp(getenv(var_name), tmpdir_backup)); + free(tmpdir_backup); + } +} + int main(int argc, char *argv[]) { test_unlink_noerrno(); test_readlink_and_make_absolute(); test_get_files_in_directory(); + test_var_tmp(); return 0; } diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index b53324b5e6..6094d4c3e5 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -114,7 +114,7 @@ static void test_find_binary(const char *self) { assert_se(find_binary(self, &p) == 0); puts(p); - assert_se(endswith(p, "/test-path-util")); + assert_se(endswith(p, "/lt-test-path-util")); assert_se(path_is_absolute(p)); free(p); diff --git a/src/test/test-strv.c b/src/test/test-strv.c index fc01dcfaf1..cf5887d258 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -685,6 +685,16 @@ static void test_foreach_string(void) { assert_se(streq(x, "zzz")); } +static void test_strv_fnmatch(void) { + _cleanup_free_ char **v = NULL; + + assert_se(!strv_fnmatch(STRV_MAKE_EMPTY, "a", 0)); + + v = strv_new("*\\*", NULL); + assert_se(!strv_fnmatch(v, "\\", 0)); + assert_se(strv_fnmatch(v, "\\", FNM_NOESCAPE)); +} + int main(int argc, char *argv[]) { test_specifier_printf(); test_strv_foreach(); @@ -750,6 +760,7 @@ int main(int argc, char *argv[]) { test_strv_make_nulstr(); test_foreach_string(); + test_strv_fnmatch(); return 0; } |