summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/fs-util.c29
-rw-r--r--src/basic/fs-util.h2
-rw-r--r--src/basic/strv.c18
-rw-r--r--src/basic/strv.h4
-rw-r--r--src/core/main.c15
-rw-r--r--src/fstab-generator/fstab-generator.c42
-rw-r--r--src/journal/journal-verify.c15
-rw-r--r--src/journal/journalctl.c48
-rw-r--r--src/libsystemd/libsystemd.sym5
-rw-r--r--src/libsystemd/sd-bus/bus-match.c3
-rw-r--r--src/libsystemd/sd-device/device-enumerator.c34
-rw-r--r--src/libsystemd/sd-device/device-internal.h2
-rw-r--r--src/libsystemd/sd-device/sd-device.c127
-rw-r--r--src/libsystemd/sd-event/sd-event.c14
-rw-r--r--src/machine/machinectl.c121
-rw-r--r--src/network/networkd-wait-online-manager.c8
-rw-r--r--src/nspawn/nspawn-patch-uid.c9
-rw-r--r--src/resolve/resolved-manager.c5
-rw-r--r--src/systemctl/systemctl.c56
-rw-r--r--src/systemd/sd-event.h1
-rw-r--r--src/test/test-fs-util.c46
-rw-r--r--src/test/test-path-util.c2
-rw-r--r--src/test/test-strv.c11
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;
}