From a3c4eb07106b29f7366113764cb1c8c4d6dd5646 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Feb 2016 15:31:33 +0100 Subject: core: rework generator dir logic, move the dirs into LookupPaths structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A long time ago – when generators where first introduced – the directories for them were randomly created via mkdtemp(). This was changed later so that they use fixed name directories now. Let's make use of this, and add the genrator dirs to the LookupPaths structure and into the unit file search path maintained in it. This has the benefit that the generator dirs are now normal part of the search path for all tools, and thus are shown in "systemctl list-unit-files" too. --- src/core/dbus-manager.c | 2 +- src/core/load-dropin.c | 2 +- src/core/load-dropin.h | 2 +- src/core/load-fragment.c | 2 +- src/core/manager.c | 142 +++++++++-------------------------------------- src/core/manager.h | 4 -- 6 files changed, 30 insertions(+), 124 deletions(-) (limited to 'src/core') diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 00372b92b4..739bd14b9e 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1924,7 +1924,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0), SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.search_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0), diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c index 22b71b6f5e..1c65055a3f 100644 --- a/src/core/load-dropin.c +++ b/src/core/load-dropin.c @@ -55,7 +55,7 @@ int unit_load_dropin(Unit *u) { SET_FOREACH(t, u->names, i) { char **p; - STRV_FOREACH(p, u->manager->lookup_paths.unit_path) { + STRV_FOREACH(p, u->manager->lookup_paths.search_path) { unit_file_process_dir(u->manager->unit_path_cache, *p, t, ".wants", UNIT_WANTS, add_dependency_consumer, u, NULL); unit_file_process_dir(u->manager->unit_path_cache, *p, t, ".requires", UNIT_REQUIRES, diff --git a/src/core/load-dropin.h b/src/core/load-dropin.h index d8a4aefbb3..942d26724e 100644 --- a/src/core/load-dropin.h +++ b/src/core/load-dropin.h @@ -25,7 +25,7 @@ /* Read service data supplementary drop-in directories */ static inline int unit_find_dropin_paths(Unit *u, char ***paths) { - return unit_file_find_dropin_paths(u->manager->lookup_paths.unit_path, + return unit_file_find_dropin_paths(u->manager->lookup_paths.search_path, u->manager->unit_path_cache, u->names, paths); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index f1a874cfdf..3a77ceb551 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -3574,7 +3574,7 @@ static int load_from_path(Unit *u, const char *path) { } else { char **p; - STRV_FOREACH(p, u->manager->lookup_paths.unit_path) { + STRV_FOREACH(p, u->manager->lookup_paths.search_path) { /* Instead of opening the path right away, we manually * follow all symlinks and add their name to our unit diff --git a/src/core/manager.c b/src/core/manager.c index e739795e70..79dc77d50e 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1053,7 +1053,7 @@ static void manager_build_unit_path_cache(Manager *m) { /* This simply builds a list of files we know exist, so that * we don't always have to go to disk */ - STRV_FOREACH(i, m->lookup_paths.unit_path) { + STRV_FOREACH(i, m->lookup_paths.search_path) { struct dirent *de; d = opendir(*i); @@ -1116,18 +1116,13 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { assert(m); - dual_timestamp_get(&m->generators_start_timestamp); - r = manager_run_generators(m); - dual_timestamp_get(&m->generators_finish_timestamp); + r = lookup_paths_init(&m->lookup_paths, m->running_as, true, NULL); if (r < 0) return r; - r = lookup_paths_init( - &m->lookup_paths, m->running_as, true, - NULL, - m->generator_unit_path, - m->generator_unit_path_early, - m->generator_unit_path_late); + dual_timestamp_get(&m->generators_start_timestamp); + r = manager_run_generators(m); + dual_timestamp_get(&m->generators_finish_timestamp); if (r < 0) return r; @@ -2542,17 +2537,12 @@ int manager_reload(Manager *m) { manager_undo_generators(m); lookup_paths_free(&m->lookup_paths); - /* Find new unit paths */ - q = manager_run_generators(m); + q = lookup_paths_init(&m->lookup_paths, m->running_as, true, NULL); if (q < 0 && r >= 0) r = q; - q = lookup_paths_init( - &m->lookup_paths, m->running_as, true, - NULL, - m->generator_unit_path, - m->generator_unit_path_early, - m->generator_unit_path_late); + /* Find new unit paths */ + q = manager_run_generators(m); if (q < 0 && r >= 0) r = q; @@ -2732,77 +2722,6 @@ void manager_check_finished(Manager *m) { manager_invalidate_startup_units(m); } -static int create_generator_dir(Manager *m, char **generator, const char *name) { - char *p; - int r; - - assert(m); - assert(generator); - assert(name); - - if (*generator) - return 0; - - if (m->running_as == MANAGER_SYSTEM && getpid() == 1) { - /* systemd --system, not running --test */ - - p = strappend("/run/systemd/", name); - if (!p) - return log_oom(); - - r = mkdir_p_label(p, 0755); - if (r < 0) { - log_error_errno(r, "Failed to create generator directory %s: %m", p); - free(p); - return r; - } - } else if (m->running_as == MANAGER_USER) { - const char *s = NULL; - - s = getenv("XDG_RUNTIME_DIR"); - if (!s) - return -EINVAL; - p = strjoin(s, "/systemd/", name, NULL); - if (!p) - return log_oom(); - - r = mkdir_p_label(p, 0755); - if (r < 0) { - log_error_errno(r, "Failed to create generator directory %s: %m", p); - free(p); - return r; - } - } else { - /* systemd --system --test */ - - p = strjoin("/tmp/systemd-", name, ".XXXXXX", NULL); - if (!p) - return log_oom(); - - if (!mkdtemp(p)) { - log_error_errno(errno, "Failed to create generator directory %s: %m", p); - free(p); - return -errno; - } - } - - *generator = p; - return 0; -} - -static void trim_generator_dir(Manager *m, char **generator) { - assert(m); - assert(generator); - - if (!*generator) - return; - - if (rmdir(*generator) >= 0) - *generator = mfree(*generator); - - return; -} - static int manager_run_generators(Manager *m) { _cleanup_strv_free_ char **paths = NULL; const char *argv[5]; @@ -2821,62 +2740,53 @@ static int manager_run_generators(Manager *m) { /* Optimize by skipping the whole process by not creating output directories * if no generators are found. */ STRV_FOREACH(path, paths) { - r = access(*path, F_OK); - if (r == 0) + if (access(*path, F_OK) >= 0) goto found; if (errno != ENOENT) log_warning_errno(errno, "Failed to open generator directory %s: %m", *path); } + return 0; found: - r = create_generator_dir(m, &m->generator_unit_path, "generator"); + r = mkdir_p_label(m->lookup_paths.generator, 0755); if (r < 0) goto finish; - r = create_generator_dir(m, &m->generator_unit_path_early, "generator.early"); + r = mkdir_p_label(m->lookup_paths.generator_early, 0755); if (r < 0) goto finish; - r = create_generator_dir(m, &m->generator_unit_path_late, "generator.late"); + r = mkdir_p_label(m->lookup_paths.generator_late, 0755); if (r < 0) goto finish; argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */ - argv[1] = m->generator_unit_path; - argv[2] = m->generator_unit_path_early; - argv[3] = m->generator_unit_path_late; + argv[1] = m->lookup_paths.generator; + argv[2] = m->lookup_paths.generator_early; + argv[3] = m->lookup_paths.generator_late; argv[4] = NULL; RUN_WITH_UMASK(0022) execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, (char**) argv); finish: - trim_generator_dir(m, &m->generator_unit_path); - trim_generator_dir(m, &m->generator_unit_path_early); - trim_generator_dir(m, &m->generator_unit_path_late); + /* Trim empty dirs */ + (void) rmdir(m->lookup_paths.generator); + (void) rmdir(m->lookup_paths.generator_early); + (void) rmdir(m->lookup_paths.generator_late); return r; } -static void remove_generator_dir(Manager *m, char **generator) { - assert(m); - assert(generator); - - if (!*generator) - return; - - strv_remove(m->lookup_paths.unit_path, *generator); - (void) rm_rf(*generator, REMOVE_ROOT); - - *generator = mfree(*generator); -} - static void manager_undo_generators(Manager *m) { assert(m); - remove_generator_dir(m, &m->generator_unit_path); - remove_generator_dir(m, &m->generator_unit_path_early); - remove_generator_dir(m, &m->generator_unit_path_late); + if (m->lookup_paths.generator) + (void) rm_rf(m->lookup_paths.generator, REMOVE_ROOT); + if (m->lookup_paths.generator_early) + (void) rm_rf(m->lookup_paths.generator_early, REMOVE_ROOT); + if (m->lookup_paths.generator_late) + (void) rm_rf(m->lookup_paths.generator_late, REMOVE_ROOT); } int manager_environment_add(Manager *m, char **minus, char **plus) { diff --git a/src/core/manager.h b/src/core/manager.h index 9803f73129..5471bd7a0d 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -162,10 +162,6 @@ struct Manager { dual_timestamp units_load_start_timestamp; dual_timestamp units_load_finish_timestamp; - char *generator_unit_path; - char *generator_unit_path_early; - char *generator_unit_path_late; - struct udev* udev; /* Data specific to the device subsystem */ -- cgit v1.2.3-54-g00ecf From 7bfe3d44d008f46d65ebdf5adc0c847b45fd4ab2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Feb 2016 16:02:48 +0100 Subject: core: when enabling a generated unit file, return a clean error Let's be precise when the user tries to invoke an "enable" operation on a generated unit file. --- src/core/dbus-manager.c | 8 ++++++-- src/libsystemd/sd-bus/bus-common-errors.c | 1 + src/libsystemd/sd-bus/bus-common-errors.h | 1 + src/shared/install.c | 10 ++++++++++ src/systemctl/systemctl.c | 4 ++++ 5 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 739bd14b9e..e187e19d03 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1648,7 +1648,9 @@ static int method_enable_unit_files_generic( r = call(scope, runtime, NULL, l, force, &changes, &n_changes); if (r == -ESHUTDOWN) - return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked"); + return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked."); + if (r == -EADDRNOTAVAIL) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, "Unit file is generated."); if (r < 0) return r; @@ -1886,7 +1888,9 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes); if (r == -ESHUTDOWN) - return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked"); + return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked."); + if (r == -EADDRNOTAVAIL) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, "Unit file is generated."); if (r < 0) return r; diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index 6370061daf..f16878cd1a 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -38,6 +38,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, EDEADLK), SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, EDEADLK), SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED, ESHUTDOWN), + SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_GENERATED, EADDRNOTAVAIL), SD_BUS_ERROR_MAP(BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, EBADR), SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION, EPERM), SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index 464834979a..c16605ba87 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -34,6 +34,7 @@ #define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic" #define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive" #define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked" +#define BUS_ERROR_UNIT_GENERATED "org.freedesktop.systemd1.UnitGenerated" #define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable" #define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation" #define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown" diff --git a/src/shared/install.c b/src/shared/install.c index 202d16e129..1e497d1492 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1761,6 +1761,8 @@ int unit_file_add_dependency( return r; if (target_info->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; + if (unit_file_is_generated(&paths, target_info->path)) + return -EADDRNOTAVAIL; assert(target_info->type == UNIT_FILE_TYPE_REGULAR); @@ -1772,6 +1774,8 @@ int unit_file_add_dependency( return r; if (i->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; + if (unit_file_is_generated(&paths, i->path)) + return -EADDRNOTAVAIL; assert(i->type == UNIT_FILE_TYPE_REGULAR); @@ -1830,6 +1834,8 @@ int unit_file_enable( return r; if (i->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; + if (unit_file_is_generated(&paths, i->path)) + return -EADDRNOTAVAIL; assert(i->type == UNIT_FILE_TYPE_REGULAR); } @@ -1957,6 +1963,8 @@ int unit_file_set_default( return r; if (i->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; + if (unit_file_is_generated(&paths, i->path)) + return -EADDRNOTAVAIL; path = strjoina(config_path, "/" SPECIAL_DEFAULT_TARGET); @@ -2254,6 +2262,8 @@ static int preset_prepare_one( if (i->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; + if (unit_file_is_generated(paths, i->path)) + return -EADDRNOTAVAIL; } else r = install_info_discover(scope, minus, root_dir, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 6394b4749e..4103a5da6d 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5473,6 +5473,8 @@ static int enable_unit(int argc, char *argv[], void *userdata) { if (r == -ESHUTDOWN) return log_error_errno(r, "Unit file is masked."); + if (r == -EADDRNOTAVAIL) + return log_error_errno(r, "Unit file is generated."); if (r < 0) return log_error_errno(r, "Operation failed: %m"); @@ -5639,6 +5641,8 @@ static int add_dependency(int argc, char *argv[], void *userdata) { r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes); if (r == -ESHUTDOWN) return log_error_errno(r, "Unit file is masked."); + if (r == -EADDRNOTAVAIL) + return log_error_errno(r, "Unit file is generated."); if (r < 0) return log_error_errno(r, "Can't add dependency: %m"); -- cgit v1.2.3-54-g00ecf From 463d0d15690c7abe2172a23ae23c5547693dd71f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Feb 2016 21:24:23 +0100 Subject: core: remove ManagerRunningAs enum Previously, we had two enums ManagerRunningAs and UnitFileScope, that were mostly identical and converted from one to the other all the time. The latter had one more value UNIT_FILE_GLOBAL however. Let's simplify things, and remove ManagerRunningAs and replace it by UnitFileScope everywhere, thus making the translation unnecessary. Introduce two new macros MANAGER_IS_SYSTEM() and MANAGER_IS_USER() to simplify checking if we are running in one or the user context. --- src/analyze/analyze-verify.c | 8 +- src/analyze/analyze-verify.h | 2 +- src/analyze/analyze.c | 2 +- src/core/automount.c | 2 +- src/core/busname.c | 4 +- src/core/cgroup.c | 4 +- src/core/dbus-manager.c | 54 ++++-------- src/core/dbus.c | 16 ++-- src/core/device.c | 2 +- src/core/failure-action.c | 2 +- src/core/job.c | 2 +- src/core/load-fragment.c | 2 +- src/core/main.c | 44 +++++----- src/core/manager.c | 89 +++++++++----------- src/core/manager.h | 9 +- src/core/mount.c | 11 ++- src/core/path.c | 2 +- src/core/service.c | 4 +- src/core/socket.c | 2 +- src/core/swap.c | 4 +- src/core/timer.c | 4 +- src/core/unit-printf.c | 2 +- src/core/unit.c | 18 ++-- src/shared/install.c | 24 +++--- src/shared/path-lookup.c | 163 ++++++++++++++++++++---------------- src/shared/path-lookup.h | 13 +-- src/systemctl/systemctl.c | 6 +- src/sysv-generator/sysv-generator.c | 2 +- src/test/test-cgroup-mask.c | 2 +- src/test/test-engine.c | 2 +- src/test/test-execute.c | 8 +- src/test/test-path-lookup.c | 23 +++-- src/test/test-path.c | 2 +- src/test/test-sched-prio.c | 2 +- src/test/test-unit-file.c | 2 +- src/test/test-unit-name.c | 2 +- 36 files changed, 258 insertions(+), 282 deletions(-) (limited to 'src/core') diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c index b83f559e7d..5fd3ee49eb 100644 --- a/src/analyze/analyze-verify.c +++ b/src/analyze/analyze-verify.c @@ -231,14 +231,12 @@ static int verify_unit(Unit *u, bool check_man) { return r; } -int verify_units(char **filenames, ManagerRunningAs running_as, bool check_man) { +int verify_units(char **filenames, UnitFileScope scope, bool check_man) { _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL; + _cleanup_free_ char *var = NULL; Manager *m = NULL; FILE *serial = NULL; FDSet *fdset = NULL; - - _cleanup_free_ char *var = NULL; - char **filename; int r = 0, k; @@ -255,7 +253,7 @@ int verify_units(char **filenames, ManagerRunningAs running_as, bool check_man) assert_se(set_unit_path(var) >= 0); - r = manager_new(running_as, true, &m); + r = manager_new(scope, true, &m); if (r < 0) return log_error_errno(r, "Failed to initialize manager: %m"); diff --git a/src/analyze/analyze-verify.h b/src/analyze/analyze-verify.h index 27c253a562..d8204dc69c 100644 --- a/src/analyze/analyze-verify.h +++ b/src/analyze/analyze-verify.h @@ -23,4 +23,4 @@ #include "path-lookup.h" -int verify_units(char **filenames, ManagerRunningAs running_as, bool check_man); +int verify_units(char **filenames, UnitFileScope scope, bool check_man); diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 42754a2741..5e03c0c5e0 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -1443,7 +1443,7 @@ int main(int argc, char *argv[]) { if (streq_ptr(argv[optind], "verify")) r = verify_units(argv+optind+1, - arg_user ? MANAGER_USER : MANAGER_SYSTEM, + arg_user ? UNIT_FILE_USER : UNIT_FILE_SYSTEM, arg_man); else { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; diff --git a/src/core/automount.c b/src/core/automount.c index 5dc6fd98e7..7c55d7bc49 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -149,7 +149,7 @@ static int automount_add_default_dependencies(Automount *a) { if (!UNIT(a)->default_dependencies) return 0; - if (UNIT(a)->manager->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(UNIT(a)->manager)) return 0; r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); diff --git a/src/core/busname.c b/src/core/busname.c index de2a21ccde..bbe61af4f0 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -149,7 +149,7 @@ static int busname_add_default_default_dependencies(BusName *n) { if (r < 0) return r; - if (UNIT(n)->manager->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(UNIT(n)->manager)) { r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true); if (r < 0) return r; @@ -318,7 +318,7 @@ static int busname_open_fd(BusName *n) { if (n->starter_fd >= 0) return 0; - mode = UNIT(n)->manager->running_as == MANAGER_SYSTEM ? "system" : "user"; + mode = MANAGER_IS_SYSTEM(UNIT(n)->manager) ? "system" : "user"; n->starter_fd = bus_kernel_open_bus_fd(mode, &path); if (n->starter_fd < 0) return log_unit_warning_errno(UNIT(n), n->starter_fd, "Failed to open %s: %m", path ?: "kdbus"); diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 9c34928052..25cc6962f9 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -1265,7 +1265,7 @@ int manager_setup_cgroup(Manager *m) { * it. This is to support live upgrades from older systemd * versions where PID 1 was moved there. Also see * cg_get_root_path(). */ - if (!e && m->running_as == MANAGER_SYSTEM) { + if (!e && MANAGER_IS_SYSTEM(m)) { e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE); if (!e) e = endswith(m->cgroup_root, "/system"); /* even more legacy */ @@ -1318,7 +1318,7 @@ int manager_setup_cgroup(Manager *m) { (void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify"); - } else if (m->running_as == MANAGER_SYSTEM) { + } else if (MANAGER_IS_SYSTEM(m)) { /* On the legacy hierarchy we only get * notifications via cgroup agents. (Which diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index e187e19d03..5fc3526751 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1187,7 +1187,7 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error * if (r < 0) return r; - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers."); m->exit_code = MANAGER_REBOOT; @@ -1206,7 +1206,7 @@ static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error if (r < 0) return r; - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers."); m->exit_code = MANAGER_POWEROFF; @@ -1225,7 +1225,7 @@ static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *er if (r < 0) return r; - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers."); m->exit_code = MANAGER_HALT; @@ -1244,7 +1244,7 @@ static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *e if (r < 0) return r; - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers."); m->exit_code = MANAGER_KEXEC; @@ -1265,7 +1265,7 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er if (r < 0) return r; - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager."); r = sd_bus_message_read(message, "ss", &root, &init); @@ -1433,7 +1433,7 @@ static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_ if (r < 0) return r; - if (m->running_as == MANAGER_SYSTEM && detect_container() <= 0) + if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "ExitCode can only be set for user service managers or in containers."); m->return_value = code; @@ -1466,7 +1466,7 @@ static int method_list_unit_files(sd_bus_message *message, void *userdata, sd_bu if (!h) return -ENOMEM; - r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h); + r = unit_file_get_list(m->unit_file_scope, NULL, h); if (r < 0) goto fail; @@ -1498,7 +1498,6 @@ static int method_get_unit_file_state(sd_bus_message *message, void *userdata, s Manager *m = userdata; const char *name; UnitFileState state; - UnitFileScope scope; int r; assert(message); @@ -1514,9 +1513,7 @@ static int method_get_unit_file_state(sd_bus_message *message, void *userdata, s if (r < 0) return r; - scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; - - r = unit_file_get_state(scope, NULL, name, &state); + r = unit_file_get_state(m->unit_file_scope, NULL, name, &state); if (r < 0) return r; @@ -1526,7 +1523,6 @@ static int method_get_unit_file_state(sd_bus_message *message, void *userdata, s static int method_get_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *default_target = NULL; Manager *m = userdata; - UnitFileScope scope; int r; assert(message); @@ -1538,9 +1534,7 @@ static int method_get_default_target(sd_bus_message *message, void *userdata, sd if (r < 0) return r; - scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; - - r = unit_file_get_default(scope, NULL, &default_target); + r = unit_file_get_default(m->unit_file_scope, NULL, &default_target); if (r < 0) return r; @@ -1624,7 +1618,6 @@ static int method_enable_unit_files_generic( _cleanup_strv_free_ char **l = NULL; UnitFileChange *changes = NULL; unsigned n_changes = 0; - UnitFileScope scope; int runtime, force, r; assert(message); @@ -1644,9 +1637,7 @@ static int method_enable_unit_files_generic( if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; - - r = call(scope, runtime, NULL, l, force, &changes, &n_changes); + r = call(m->unit_file_scope, runtime, NULL, l, force, &changes, &n_changes); if (r == -ESHUTDOWN) return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked."); if (r == -EADDRNOTAVAIL) @@ -1688,7 +1679,6 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use unsigned n_changes = 0; Manager *m = userdata; UnitFilePresetMode mm; - UnitFileScope scope; int runtime, force, r; const char *mode; @@ -1717,9 +1707,7 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; - - r = unit_file_preset(scope, runtime, NULL, l, mm, force, &changes, &n_changes); + r = unit_file_preset(m->unit_file_scope, runtime, NULL, l, mm, force, &changes, &n_changes); if (r < 0) return r; @@ -1736,7 +1724,6 @@ static int method_disable_unit_files_generic( _cleanup_strv_free_ char **l = NULL; UnitFileChange *changes = NULL; unsigned n_changes = 0; - UnitFileScope scope; int r, runtime; assert(message); @@ -1750,15 +1737,13 @@ static int method_disable_unit_files_generic( if (r < 0) return r; - scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; - r = bus_verify_manage_unit_files_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - r = call(scope, runtime, NULL, l, &changes, &n_changes); + r = call(m->unit_file_scope, runtime, NULL, l, &changes, &n_changes); if (r < 0) return r; @@ -1777,7 +1762,6 @@ static int method_set_default_target(sd_bus_message *message, void *userdata, sd UnitFileChange *changes = NULL; unsigned n_changes = 0; Manager *m = userdata; - UnitFileScope scope; const char *name; int force, r; @@ -1798,9 +1782,7 @@ static int method_set_default_target(sd_bus_message *message, void *userdata, sd if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; - - r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes); + r = unit_file_set_default(m->unit_file_scope, NULL, name, force, &changes, &n_changes); if (r < 0) return r; @@ -1812,7 +1794,6 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, unsigned n_changes = 0; Manager *m = userdata; UnitFilePresetMode mm; - UnitFileScope scope; const char *mode; int force, runtime, r; @@ -1841,9 +1822,7 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; - - r = unit_file_preset_all(scope, runtime, NULL, mm, force, &changes, &n_changes); + r = unit_file_preset_all(m->unit_file_scope, runtime, NULL, mm, force, &changes, &n_changes); if (r < 0) { unit_file_changes_free(changes, n_changes); return r; @@ -1857,7 +1836,6 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd Manager *m = userdata; UnitFileChange *changes = NULL; unsigned n_changes = 0; - UnitFileScope scope; int runtime, force, r; char *target; char *type; @@ -1884,9 +1862,7 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd if (dep < 0) return -EINVAL; - scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; - - r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes); + r = unit_file_add_dependency(m->unit_file_scope, runtime, NULL, l, target, dep, force, &changes, &n_changes); if (r == -ESHUTDOWN) return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked."); if (r == -EADDRNOTAVAIL) diff --git a/src/core/dbus.c b/src/core/dbus.c index 413489373f..263955d874 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -112,7 +112,7 @@ static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus manager_notify_cgroup_empty(m, cgroup); /* if running as system-instance, forward under our name */ - if (m->running_as == MANAGER_SYSTEM && m->system_bus) { + if (MANAGER_IS_SYSTEM(m) && m->system_bus) { r = sd_bus_message_rewind(message, 1); if (r >= 0) r = sd_bus_send(m->system_bus, message, NULL); @@ -690,7 +690,7 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void return 0; } - if (m->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(m)) { /* When we run as system instance we get the Released * signal via a direct connection */ @@ -864,10 +864,10 @@ static int bus_init_api(Manager *m) { return 0; /* The API and system bus is the same if we are running in system mode */ - if (m->running_as == MANAGER_SYSTEM && m->system_bus) + if (MANAGER_IS_SYSTEM(m) && m->system_bus) bus = sd_bus_ref(m->system_bus); else { - if (m->running_as == MANAGER_SYSTEM) + if (MANAGER_IS_SYSTEM(m)) r = sd_bus_open_system(&bus); else r = sd_bus_open_user(&bus); @@ -907,7 +907,7 @@ static int bus_setup_system(Manager *m, sd_bus *bus) { assert(bus); /* On kdbus or if we are a user instance we get the Released message via the system bus */ - if (m->running_as == MANAGER_USER || m->kdbus_fd >= 0) { + if (MANAGER_IS_USER(m) || m->kdbus_fd >= 0) { r = sd_bus_add_match( bus, NULL, @@ -932,7 +932,7 @@ static int bus_init_system(Manager *m) { return 0; /* The API and system bus is the same if we are running in system mode */ - if (m->running_as == MANAGER_SYSTEM && m->api_bus) { + if (MANAGER_IS_SYSTEM(m) && m->api_bus) { m->system_bus = sd_bus_ref(m->api_bus); return 0; } @@ -983,7 +983,7 @@ static int bus_init_private(Manager *m) { if (m->kdbus_fd >= 0) return 0; - if (m->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(m)) { /* We want the private bus only when running as init */ if (getpid() != 1) @@ -1082,7 +1082,7 @@ static void destroy_bus(Manager *m, sd_bus **bus) { /* Possibly flush unwritten data, but only if we are * unprivileged, since we don't want to sync here */ - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) sd_bus_flush(*bus); /* And destroy the object */ diff --git a/src/core/device.c b/src/core/device.c index 0671620a3e..d01bec53d8 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -265,7 +265,7 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) { assert(u); assert(dev); - property = u->manager->running_as == MANAGER_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS"; + property = MANAGER_IS_USER(u->manager) ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS"; wants = udev_device_get_property_value(dev, property); if (!wants) return 0; diff --git a/src/core/failure-action.c b/src/core/failure-action.c index bb2bc3f399..d4aae4b6e7 100644 --- a/src/core/failure-action.c +++ b/src/core/failure-action.c @@ -47,7 +47,7 @@ int failure_action( if (action == FAILURE_ACTION_NONE) return -ECANCELED; - if (m->running_as == MANAGER_USER) { + if (!MANAGER_IS_SYSTEM(m)) { /* Downgrade all options to simply exiting if we run * in user mode */ diff --git a/src/core/job.c b/src/core/job.c index 5557a6a942..2e30431163 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -1156,7 +1156,7 @@ void job_shutdown_magic(Job *j) { if (j->type != JOB_START) return; - if (j->unit->manager->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(j->unit->manager)) return; if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET)) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 3a77ceb551..79f13f135d 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2495,7 +2495,7 @@ int config_parse_syscall_filter( /* Turn on NNP, but only if it wasn't configured explicitly * before, and only if we are in user mode. */ - if (!c->no_new_privileges_set && u->manager->running_as == MANAGER_USER) + if (!c->no_new_privileges_set && MANAGER_IS_USER(u->manager)) c->no_new_privileges = true; return 0; diff --git a/src/core/main.c b/src/core/main.c index 56df32426a..a428e345e0 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -94,7 +94,7 @@ static enum { ACTION_DONE } arg_action = ACTION_RUN; static char *arg_default_unit = NULL; -static ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID; +static bool arg_system = false; static bool arg_dump_core = true; static int arg_crash_chvt = -1; static bool arg_crash_shell = false; @@ -688,11 +688,11 @@ static int parse_config_file(void) { const char *fn, *conf_dirs_nulstr; - fn = arg_running_as == MANAGER_SYSTEM ? + fn = arg_system ? PKGSYSCONFDIR "/system.conf" : PKGSYSCONFDIR "/user.conf"; - conf_dirs_nulstr = arg_running_as == MANAGER_SYSTEM ? + conf_dirs_nulstr = arg_system ? CONF_PATHS_NULSTR("systemd/system.conf.d") : CONF_PATHS_NULSTR("systemd/user.conf.d"); @@ -866,11 +866,11 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_SYSTEM: - arg_running_as = MANAGER_SYSTEM; + arg_system = true; break; case ARG_USER: - arg_running_as = MANAGER_USER; + arg_system = false; break; case ARG_TEST: @@ -1346,7 +1346,7 @@ int main(int argc, char *argv[]) { if (getpid() == 1 && detect_container() <= 0) { /* Running outside of a container as PID 1 */ - arg_running_as = MANAGER_SYSTEM; + arg_system = true; make_null_stdio(); log_set_target(LOG_TARGET_KMSG); log_open(); @@ -1430,7 +1430,7 @@ int main(int argc, char *argv[]) { } else if (getpid() == 1) { /* Running inside a container, as PID 1 */ - arg_running_as = MANAGER_SYSTEM; + arg_system = true; log_set_target(LOG_TARGET_CONSOLE); log_close_console(); /* force reopen of /dev/console */ log_open(); @@ -1443,7 +1443,7 @@ int main(int argc, char *argv[]) { kernel_timestamp = DUAL_TIMESTAMP_NULL; } else { /* Running as user instance */ - arg_running_as = MANAGER_USER; + arg_system = false; log_set_target(LOG_TARGET_AUTO); log_open(); @@ -1501,7 +1501,7 @@ int main(int argc, char *argv[]) { goto finish; } - if (arg_running_as == MANAGER_SYSTEM) { + if (arg_system) { r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); @@ -1522,14 +1522,14 @@ int main(int argc, char *argv[]) { goto finish; } - if (arg_running_as == MANAGER_USER && + if (!arg_system && arg_action == ACTION_RUN && sd_booted() <= 0) { log_error("Trying to run as user instance, but the system has not been booted with systemd."); goto finish; } - if (arg_running_as == MANAGER_SYSTEM && + if (arg_system && arg_action == ACTION_RUN && running_in_chroot() > 0) { log_error("Cannot be run in a chroot() environment."); @@ -1557,7 +1557,7 @@ int main(int argc, char *argv[]) { goto finish; } - if (arg_running_as == MANAGER_USER && + if (!arg_system && !getenv("XDG_RUNTIME_DIR")) { log_error("Trying to run as user instance, but $XDG_RUNTIME_DIR is not set."); goto finish; @@ -1580,7 +1580,7 @@ int main(int argc, char *argv[]) { if (arg_serialization) assert_se(fdset_remove(fds, fileno(arg_serialization)) >= 0); - if (arg_running_as == MANAGER_SYSTEM) + if (arg_system) /* Become a session leader if we aren't one yet. */ setsid(); @@ -1589,7 +1589,7 @@ int main(int argc, char *argv[]) { /* Reset the console, but only if this is really init and we * are freshly booted */ - if (arg_running_as == MANAGER_SYSTEM && arg_action == ACTION_RUN) { + if (arg_system && arg_action == ACTION_RUN) { /* If we are init, we connect stdin/stdout/stderr to * /dev/null and make sure we don't have a controlling @@ -1616,7 +1616,7 @@ int main(int argc, char *argv[]) { goto finish; } - if (arg_running_as == MANAGER_SYSTEM) { + if (arg_system) { int v; log_info(PACKAGE_STRING " running in %ssystem mode. (" SYSTEMD_FEATURES ")", @@ -1652,7 +1652,7 @@ int main(int argc, char *argv[]) { arg_action == ACTION_TEST ? " test" : "", getuid(), t); } - if (arg_running_as == MANAGER_SYSTEM && !skip_setup) { + if (arg_system && !skip_setup) { if (arg_show_status > 0) status_welcome(); @@ -1664,7 +1664,7 @@ int main(int argc, char *argv[]) { test_usr(); } - if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY) + if (arg_system && arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY) watchdog_set_timeout(&arg_runtime_watchdog); if (arg_timer_slack_nsec != NSEC_INFINITY) @@ -1694,12 +1694,12 @@ int main(int argc, char *argv[]) { } } - if (arg_running_as == MANAGER_USER) + if (!arg_system) /* Become reaper of our children */ if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) log_warning_errno(errno, "Failed to make us a subreaper: %m"); - if (arg_running_as == MANAGER_SYSTEM) { + if (arg_system) { bump_rlimit_nofile(&saved_rlimit_nofile); if (empty_etc) { @@ -1711,7 +1711,7 @@ int main(int argc, char *argv[]) { } } - r = manager_new(arg_running_as, arg_action == ACTION_TEST, &m); + r = manager_new(arg_system ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, arg_action == ACTION_TEST, &m); if (r < 0) { log_emergency_errno(r, "Failed to allocate manager object: %m"); error_message = "Failed to allocate manager object"; @@ -1874,7 +1874,7 @@ int main(int argc, char *argv[]) { case MANAGER_EXIT: retval = m->return_value; - if (m->running_as == MANAGER_USER) { + if (MANAGER_IS_USER(m)) { log_debug("Exit."); goto finish; } @@ -1970,7 +1970,7 @@ finish: args[i++] = SYSTEMD_BINARY_PATH; if (switch_root_dir) args[i++] = "--switched-root"; - args[i++] = arg_running_as == MANAGER_SYSTEM ? "--system" : "--user"; + args[i++] = arg_system ? "--system" : "--user"; args[i++] = "--deserialize"; args[i++] = sfd; args[i++] = NULL; diff --git a/src/core/manager.c b/src/core/manager.c index 79dc77d50e..1412d6718a 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -491,7 +491,7 @@ static int manager_setup_signals(Manager *m) { if (r < 0) return r; - if (m->running_as == MANAGER_SYSTEM) + if (MANAGER_IS_SYSTEM(m)) return enable_special_signals(m); return 0; @@ -518,7 +518,7 @@ static void manager_clean_environment(Manager *m) { static int manager_default_environment(Manager *m) { assert(m); - if (m->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(m)) { /* The system manager always starts with a clean * environment for its children. It does not import * the kernel or the parents exported variables. @@ -547,43 +547,36 @@ static int manager_default_environment(Manager *m) { } -int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) { - - static const char * const unit_log_fields[_MANAGER_RUNNING_AS_MAX] = { - [MANAGER_SYSTEM] = "UNIT=", - [MANAGER_USER] = "USER_UNIT=", - }; - - static const char * const unit_log_format_strings[_MANAGER_RUNNING_AS_MAX] = { - [MANAGER_SYSTEM] = "UNIT=%s", - [MANAGER_USER] = "USER_UNIT=%s", - }; - +int manager_new(UnitFileScope scope, bool test_run, Manager **_m) { Manager *m; int r; assert(_m); - assert(running_as >= 0); - assert(running_as < _MANAGER_RUNNING_AS_MAX); + assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER)); m = new0(Manager, 1); if (!m) return -ENOMEM; -#ifdef ENABLE_EFI - if (running_as == MANAGER_SYSTEM && detect_container() <= 0) - boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp); -#endif - - m->running_as = running_as; + m->unit_file_scope = scope; m->exit_code = _MANAGER_EXIT_CODE_INVALID; m->default_timer_accuracy_usec = USEC_PER_MINUTE; m->default_tasks_accounting = true; m->default_tasks_max = UINT64_C(512); +#ifdef ENABLE_EFI + if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0) + boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp); +#endif + /* Prepare log fields we can use for structured logging */ - m->unit_log_field = unit_log_fields[running_as]; - m->unit_log_format_string = unit_log_format_strings[running_as]; + if (MANAGER_IS_SYSTEM(m)) { + m->unit_log_field = "UNIT="; + m->unit_log_format_string = "UNIT=%s"; + } else { + m->unit_log_field = "USER_UNIT="; + m->unit_log_format_string = "USER_UNIT=%s"; + } m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1; @@ -694,7 +687,7 @@ static int manager_setup_notify(Manager *m) { fd_inc_rcvbuf(fd, NOTIFY_RCVBUF_SIZE); - if (m->running_as == MANAGER_SYSTEM) + if (MANAGER_IS_SYSTEM(m)) m->notify_socket = strdup("/run/systemd/notify"); else { const char *e; @@ -756,8 +749,8 @@ static int manager_setup_kdbus(Manager *m) { return -ESOCKTNOSUPPORT; m->kdbus_fd = bus_kernel_create_bus( - m->running_as == MANAGER_SYSTEM ? "system" : "user", - m->running_as == MANAGER_SYSTEM, &p); + MANAGER_IS_SYSTEM(m) ? "system" : "user", + MANAGER_IS_SYSTEM(m), &p); if (m->kdbus_fd < 0) return log_debug_errno(m->kdbus_fd, "Failed to set up kdbus: %m"); @@ -778,7 +771,7 @@ static int manager_connect_bus(Manager *m, bool reexecuting) { try_bus_connect = m->kdbus_fd >= 0 || reexecuting || - (m->running_as == MANAGER_USER && getenv("DBUS_SESSION_BUS_ADDRESS")); + (MANAGER_IS_USER(m) && getenv("DBUS_SESSION_BUS_ADDRESS")); /* Try to connect to the buses, if possible. */ return bus_init(m, try_bus_connect); @@ -1116,7 +1109,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { assert(m); - r = lookup_paths_init(&m->lookup_paths, m->running_as, true, NULL); + r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, NULL); if (r < 0) return r; @@ -1739,7 +1732,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t } log_received_signal(sfsi.ssi_signo == SIGCHLD || - (sfsi.ssi_signo == SIGTERM && m->running_as == MANAGER_USER) + (sfsi.ssi_signo == SIGTERM && MANAGER_IS_USER(m)) ? LOG_DEBUG : LOG_INFO, &sfsi); @@ -1750,7 +1743,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t break; case SIGTERM: - if (m->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(m)) { /* This is for compatibility with the * original sysvinit */ m->exit_code = MANAGER_REEXECUTE; @@ -1760,7 +1753,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t /* Fall through */ case SIGINT: - if (m->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(m)) { /* If the user presses C-A-D more than * 7 times within 2s, we reboot @@ -1786,14 +1779,14 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t break; case SIGWINCH: - if (m->running_as == MANAGER_SYSTEM) + if (MANAGER_IS_SYSTEM(m)) manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE); /* This is a nop on non-init */ break; case SIGPWR: - if (m->running_as == MANAGER_SYSTEM) + if (MANAGER_IS_SYSTEM(m)) manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE); /* This is a nop on non-init */ @@ -1901,7 +1894,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t break; case 24: - if (m->running_as == MANAGER_USER) { + if (MANAGER_IS_USER(m)) { m->exit_code = MANAGER_EXIT; return 0; } @@ -2017,7 +2010,7 @@ int manager_loop(Manager *m) { while (m->exit_code == MANAGER_OK) { usec_t wait_usec; - if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && m->running_as == MANAGER_SYSTEM) + if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && MANAGER_IS_SYSTEM(m)) watchdog_ping(); if (!ratelimit_test(&rl)) { @@ -2042,7 +2035,7 @@ int manager_loop(Manager *m) { continue; /* Sleep for half the watchdog time */ - if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && m->running_as == MANAGER_SYSTEM) { + if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && MANAGER_IS_SYSTEM(m)) { wait_usec = m->runtime_watchdog / 2; if (wait_usec <= 0) wait_usec = 1; @@ -2113,7 +2106,7 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { const char *msg; int audit_fd, r; - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return; audit_fd = get_audit_fd(); @@ -2159,7 +2152,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) { if (m->n_reloading > 0) return; - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return; if (detect_container() > 0) @@ -2203,7 +2196,7 @@ int manager_open_serialization(Manager *m, FILE **_f) { assert(_f); - path = m->running_as == MANAGER_SYSTEM ? "/run/systemd" : "/tmp"; + path = MANAGER_IS_SYSTEM(m) ? "/run/systemd" : "/tmp"; fd = open_tmpfile(path, O_RDWR|O_CLOEXEC); if (fd < 0) return -errno; @@ -2537,7 +2530,7 @@ int manager_reload(Manager *m) { manager_undo_generators(m); lookup_paths_free(&m->lookup_paths); - q = lookup_paths_init(&m->lookup_paths, m->running_as, true, NULL); + q = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, NULL); if (q < 0 && r >= 0) r = q; @@ -2616,7 +2609,7 @@ static void manager_notify_finished(Manager *m) { if (m->test_run) return; - if (m->running_as == MANAGER_SYSTEM && detect_container() <= 0) { + if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0) { /* Note that m->kernel_usec.monotonic is always at 0, * and m->firmware_usec.monotonic and @@ -2733,7 +2726,7 @@ static int manager_run_generators(Manager *m) { if (m->test_run) return 0; - paths = generator_paths(m->running_as); + paths = generator_paths(m->unit_file_scope); if (!paths) return log_oom(); @@ -2851,7 +2844,7 @@ void manager_recheck_journal(Manager *m) { assert(m); - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return; u = manager_get_unit(m, SPECIAL_JOURNALD_SOCKET); @@ -2875,7 +2868,7 @@ void manager_set_show_status(Manager *m, ShowStatus mode) { assert(m); assert(IN_SET(mode, SHOW_STATUS_AUTO, SHOW_STATUS_NO, SHOW_STATUS_YES, SHOW_STATUS_TEMPORARY)); - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return; if (m->show_status != mode) @@ -2892,7 +2885,7 @@ void manager_set_show_status(Manager *m, ShowStatus mode) { static bool manager_get_show_status(Manager *m, StatusType type) { assert(m); - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return false; if (m->no_console_output) @@ -2914,7 +2907,7 @@ static bool manager_get_show_status(Manager *m, StatusType type) { void manager_set_first_boot(Manager *m, bool b) { assert(m); - if (m->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(m)) return; if (m->first_boot != (int) b) { @@ -2960,7 +2953,7 @@ Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) { const char *manager_get_runtime_prefix(Manager *m) { assert(m); - return m->running_as == MANAGER_SYSTEM ? + return MANAGER_IS_SYSTEM(m) ? "/run" : getenv("XDG_RUNTIME_DIR"); } diff --git a/src/core/manager.h b/src/core/manager.h index 5471bd7a0d..19eab958ea 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -140,6 +140,7 @@ struct Manager { sd_event_source *jobs_in_progress_event_source; + UnitFileScope unit_file_scope; LookupPaths lookup_paths; Set *unit_path_cache; @@ -224,7 +225,6 @@ struct Manager { unsigned n_in_gc_queue; /* Flags */ - ManagerRunningAs running_as; ManagerExitCode exit_code:5; bool dispatching_load_queue:1; @@ -300,10 +300,13 @@ struct Manager { const char *unit_log_field; const char *unit_log_format_string; - int first_boot; + int first_boot; /* tri-state */ }; -int manager_new(ManagerRunningAs running_as, bool test_run, Manager **m); +#define MANAGER_IS_SYSTEM(m) ((m)->unit_file_scope == UNIT_FILE_SYSTEM) +#define MANAGER_IS_USER(m) ((m)->unit_file_scope != UNIT_FILE_SYSTEM) + +int manager_new(UnitFileScope scope, bool test_run, Manager **m); Manager* manager_free(Manager *m); void manager_enumerate(Manager *m); diff --git a/src/core/mount.c b/src/core/mount.c index 0fd880df5d..74ab54bfd0 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -336,8 +336,7 @@ static int mount_add_device_links(Mount *m) { if (path_equal(m->where, "/")) return 0; - if (mount_is_auto(p) && !mount_is_automount(p) && - UNIT(m)->manager->running_as == MANAGER_SYSTEM) + if (mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager)) device_wants_mount = true; r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, m->from_fragment ? UNIT_BINDS_TO : UNIT_REQUIRES); @@ -353,7 +352,7 @@ static int mount_add_quota_links(Mount *m) { assert(m); - if (UNIT(m)->manager->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) return 0; p = get_mount_parameters_fragment(m); @@ -400,7 +399,7 @@ static int mount_add_default_dependencies(Mount *m) { if (!UNIT(m)->default_dependencies) return 0; - if (UNIT(m)->manager->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) return 0; /* We do not add any default dependencies to /, /usr or @@ -1396,7 +1395,7 @@ static int mount_setup_unit( goto fail; } - if (m->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(m)) { const char* target; target = mount_needs_network(options, fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET; @@ -1424,7 +1423,7 @@ static int mount_setup_unit( } } - if (m->running_as == MANAGER_SYSTEM && + if (MANAGER_IS_SYSTEM(m) && mount_needs_network(options, fstype)) { /* _netdev option may have shown up late, or on a * remount. Add remote-fs dependencies, even though diff --git a/src/core/path.c b/src/core/path.c index 426c4ad299..5e7b3eb234 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -318,7 +318,7 @@ static int path_add_default_dependencies(Path *p) { if (r < 0) return r; - if (UNIT(p)->manager->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(UNIT(p)->manager)) { r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true); if (r < 0) return r; diff --git a/src/core/service.c b/src/core/service.c index c5cbf0f152..7aea6f7ff4 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -523,7 +523,7 @@ static int service_add_default_dependencies(Service *s) { /* Add a number of automatic dependencies useful for the * majority of services. */ - if (UNIT(s)->manager->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(UNIT(s)->manager)) { /* First, pull in the really early boot stuff, and * require it, so that we fail if we can't acquire * it. */ @@ -1211,7 +1211,7 @@ static int service_spawn( if (asprintf(our_env + n_env++, "MAINPID="PID_FMT, s->main_pid) < 0) return -ENOMEM; - if (UNIT(s)->manager->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(UNIT(s)->manager)) if (asprintf(our_env + n_env++, "MANAGERPID="PID_FMT, getpid()) < 0) return -ENOMEM; diff --git a/src/core/socket.c b/src/core/socket.c index dd515a17a5..65da0e3c5e 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -301,7 +301,7 @@ static int socket_add_default_dependencies(Socket *s) { if (r < 0) return r; - if (UNIT(s)->manager->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(UNIT(s)->manager)) { r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true); if (r < 0) return r; diff --git a/src/core/swap.c b/src/core/swap.c index 11506d9ecb..c6502eb821 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -198,7 +198,7 @@ static int swap_add_device_links(Swap *s) { return 0; if (is_device_path(s->what)) - return unit_add_node_link(UNIT(s), s->what, UNIT(s)->manager->running_as == MANAGER_SYSTEM, UNIT_BINDS_TO); + return unit_add_node_link(UNIT(s), s->what, MANAGER_IS_SYSTEM(UNIT(s)->manager), UNIT_BINDS_TO); else /* File based swap devices need to be ordered after * systemd-remount-fs.service, since they might need a @@ -214,7 +214,7 @@ static int swap_add_default_dependencies(Swap *s) { if (!UNIT(s)->default_dependencies) return 0; - if (UNIT(s)->manager->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(UNIT(s)->manager)) return 0; if (detect_container() > 0) diff --git a/src/core/timer.c b/src/core/timer.c index 3d0bae16e5..a51a67ea11 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -109,7 +109,7 @@ static int timer_add_default_dependencies(Timer *t) { if (r < 0) return r; - if (UNIT(t)->manager->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) { r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true); if (r < 0) return r; @@ -135,7 +135,7 @@ static int timer_setup_persistent(Timer *t) { if (!t->persistent) return 0; - if (UNIT(t)->manager->running_as == MANAGER_SYSTEM) { + if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) { r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers"); if (r < 0) diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c index fc057d965c..40da52fcac 100644 --- a/src/core/unit-printf.c +++ b/src/core/unit-printf.c @@ -140,7 +140,7 @@ static int specifier_runtime(char specifier, void *data, void *userdata, char ** assert(u); - if (u->manager->running_as == MANAGER_SYSTEM) + if (MANAGER_IS_SYSTEM(u->manager)) e = "/run"; else { e = getenv("XDG_RUNTIME_DIR"); diff --git a/src/core/unit.c b/src/core/unit.c index 70175557f7..fbc2b0d74d 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -814,7 +814,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) { return r; } - if (u->manager->running_as != MANAGER_SYSTEM) + if (!MANAGER_IS_SYSTEM(u->manager)) return 0; if (c->private_tmp) { @@ -2413,7 +2413,7 @@ int unit_set_default_slice(Unit *u) { if (!escaped) return -ENOMEM; - if (u->manager->running_as == MANAGER_SYSTEM) + if (MANAGER_IS_SYSTEM(u->manager)) b = strjoin("system-", escaped, ".slice", NULL); else b = strappend(escaped, ".slice"); @@ -2423,7 +2423,7 @@ int unit_set_default_slice(Unit *u) { slice_name = b; } else slice_name = - u->manager->running_as == MANAGER_SYSTEM && !unit_has_name(u, SPECIAL_INIT_SCOPE) + MANAGER_IS_SYSTEM(u->manager) && !unit_has_name(u, SPECIAL_INIT_SCOPE) ? SPECIAL_SYSTEM_SLICE : SPECIAL_ROOT_SLICE; @@ -2884,7 +2884,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep return r; r = unit_add_two_dependencies(u, UNIT_AFTER, - u->manager->running_as == MANAGER_SYSTEM ? dep : UNIT_WANTS, + MANAGER_IS_SYSTEM(u->manager) ? dep : UNIT_WANTS, device, true); if (r < 0) return r; @@ -3158,7 +3158,7 @@ UnitFileState unit_get_unit_file_state(Unit *u) { if (u->unit_file_state < 0 && u->fragment_path) { r = unit_file_get_state( - u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, + u->manager->unit_file_scope, NULL, basename(u->fragment_path), &u->unit_file_state); @@ -3174,7 +3174,7 @@ int unit_get_unit_file_preset(Unit *u) { if (u->unit_file_preset < 0 && u->fragment_path) u->unit_file_preset = unit_file_query_preset( - u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, + u->manager->unit_file_scope, NULL, basename(u->fragment_path)); @@ -3225,7 +3225,7 @@ int unit_patch_contexts(Unit *u) { return -ENOMEM; } - if (u->manager->running_as == MANAGER_USER && + if (MANAGER_IS_USER(u->manager) && !ec->working_directory) { r = get_home_dir(&ec->working_directory); @@ -3237,7 +3237,7 @@ int unit_patch_contexts(Unit *u) { ec->working_directory_missing_ok = true; } - if (u->manager->running_as == MANAGER_USER && + if (MANAGER_IS_USER(u->manager) && (ec->syscall_whitelist || !set_isempty(ec->syscall_filter) || !set_isempty(ec->syscall_archs) || @@ -3318,7 +3318,7 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) { static int unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode, bool transient, char **dir) { assert(u); - if (u->manager->running_as == MANAGER_USER) { + if (MANAGER_IS_USER(u->manager)) { int r; if (mode == UNIT_PERSISTENT && !transient) diff --git a/src/shared/install.c b/src/shared/install.c index 2cec6ba76f..f802343399 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1442,7 +1442,7 @@ int unit_file_mask( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -1493,7 +1493,7 @@ int unit_file_unmask( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -1575,7 +1575,7 @@ int unit_file_link( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -1668,7 +1668,7 @@ int unit_file_add_dependency( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -1738,7 +1738,7 @@ int unit_file_enable( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -1786,7 +1786,7 @@ int unit_file_disable( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -1863,7 +1863,7 @@ int unit_file_set_default( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -1899,7 +1899,7 @@ int unit_file_get_default( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -2001,7 +2001,7 @@ int unit_file_get_state( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -2203,7 +2203,7 @@ int unit_file_preset( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -2244,7 +2244,7 @@ int unit_file_preset_all( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; @@ -2322,7 +2322,7 @@ int unit_file_get_list( if (r < 0) return r; - r = lookup_paths_init_from_scope(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, root_dir); if (r < 0) return r; diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index 5766053cef..cfe62c6438 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -102,7 +102,7 @@ static int user_data_home_dir(char **dir, const char *suffix) { return -ENOMEM; *dir = res; - return 0; + return 1; } static char** user_dirs( @@ -223,23 +223,32 @@ static char** user_dirs( return tmp; } -char **generator_paths(ManagerRunningAs running_as) { - if (running_as == MANAGER_USER) - return strv_new("/run/systemd/user-generators", - "/etc/systemd/user-generators", - "/usr/local/lib/systemd/user-generators", - USER_GENERATOR_PATH, - NULL); - else +char **generator_paths(UnitFileScope scope) { + + switch (scope) { + + case UNIT_FILE_SYSTEM: return strv_new("/run/systemd/system-generators", "/etc/systemd/system-generators", "/usr/local/lib/systemd/system-generators", SYSTEM_GENERATOR_PATH, NULL); + + case UNIT_FILE_GLOBAL: + case UNIT_FILE_USER: + return strv_new("/run/systemd/user-generators", + "/etc/systemd/user-generators", + "/usr/local/lib/systemd/user-generators", + USER_GENERATOR_PATH, + NULL); + + default: + assert_not_reached("Hmm, unexpected scope."); + } } static int acquire_generator_dirs( - ManagerRunningAs running_as, + UnitFileScope scope, char **generator, char **generator_early, char **generator_late) { @@ -251,18 +260,28 @@ static int acquire_generator_dirs( assert(generator_early); assert(generator_late); - if (running_as == MANAGER_SYSTEM) + switch (scope) { + + case UNIT_FILE_SYSTEM: prefix = "/run/systemd/"; - else { - const char *e; + break; - assert(running_as == MANAGER_USER); + case UNIT_FILE_USER: { + const char *e; e = getenv("XDG_RUNTIME_DIR"); if (!e) - return -EINVAL; + return -ENXIO; prefix = strjoina(e, "/systemd/", NULL); + break; + } + + case UNIT_FILE_GLOBAL: + return -EOPNOTSUPP; + + default: + assert_not_reached("Hmm, unexpected scope value."); } x = strappend(prefix, "generator"); @@ -285,19 +304,26 @@ static int acquire_generator_dirs( return 0; } -static int acquire_config_dirs(ManagerRunningAs running_as, bool personal, char **persistent, char **runtime) { +static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **runtime) { _cleanup_free_ char *a = NULL, *b = NULL; int r; assert(persistent); assert(runtime); - if (running_as == MANAGER_SYSTEM) { + switch (scope) { + + case UNIT_FILE_SYSTEM: a = strdup(SYSTEM_CONFIG_UNIT_PATH); b = strdup("/run/systemd/system"); - } else if (personal) { - assert(running_as == MANAGER_USER); + break; + + case UNIT_FILE_GLOBAL: + a = strdup(USER_CONFIG_UNIT_PATH); + b = strdup("/run/systemd/user"); + break; + case UNIT_FILE_USER: r = user_config_home(&a); if (r < 0) return r; @@ -310,11 +336,9 @@ static int acquire_config_dirs(ManagerRunningAs running_as, bool personal, char a = NULL; return 0; - } else { - assert(running_as == MANAGER_USER); - a = strdup(USER_CONFIG_UNIT_PATH); - b = strdup("/run/systemd/user"); + default: + assert_not_reached("Hmm, unexpected scope value."); } if (!a || !b) @@ -350,8 +374,7 @@ static int patch_root_prefix(char **p, const char *root_dir) { int lookup_paths_init( LookupPaths *p, - ManagerRunningAs running_as, - bool personal, + UnitFileScope scope, const char *root_dir) { _cleanup_free_ char *generator = NULL, *generator_early = NULL, *generator_late = NULL, @@ -362,15 +385,15 @@ int lookup_paths_init( int r; assert(p); - assert(running_as >= 0); - assert(running_as < _MANAGER_RUNNING_AS_MAX); + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); - r = acquire_config_dirs(running_as, personal, &persistent_config, &runtime_config); + r = acquire_config_dirs(scope, &persistent_config, &runtime_config); if (r < 0) return r; - r = acquire_generator_dirs(running_as, &generator, &generator_early, &generator_late); - if (r < 0) + r = acquire_generator_dirs(scope, &generator, &generator_early, &generator_late); + if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO) return r; /* First priority is whatever has been passed to us via env @@ -405,46 +428,56 @@ int lookup_paths_init( * we include /lib in the search path for the system * stuff but avoid it for user stuff. */ - if (running_as == MANAGER_USER) { - if (personal) - add = user_dirs(persistent_config, runtime_config, - generator, generator_early, generator_late); - else - add = strv_new( + switch (scope) { + + case UNIT_FILE_SYSTEM: + add = strv_new( + /* If you modify this you also want to modify + * systemdsystemunitpath= in systemd.pc.in! */ + STRV_IFNOTNULL(generator_early), + persistent_config, + "/etc/systemd/system", + runtime_config, + "/run/systemd/system", + STRV_IFNOTNULL(generator), + "/usr/local/lib/systemd/system", + SYSTEM_DATA_UNIT_PATH, + "/usr/lib/systemd/system", +#ifdef HAVE_SPLIT_USR + "/lib/systemd/system", +#endif + STRV_IFNOTNULL(generator_late), + NULL); + break; + + case UNIT_FILE_GLOBAL: + add = strv_new( /* If you modify this you also want to modify * systemduserunitpath= in systemd.pc.in, and * the arrays in user_dirs() above! */ - generator_early, + STRV_IFNOTNULL(generator_early), persistent_config, "/etc/systemd/user", runtime_config, "/run/systemd/user", - generator, + STRV_IFNOTNULL(generator), "/usr/local/lib/systemd/user", "/usr/local/share/systemd/user", USER_DATA_UNIT_PATH, "/usr/lib/systemd/user", "/usr/share/systemd/user", - generator_late, + STRV_IFNOTNULL(generator_late), NULL); - } else - add = strv_new( - /* If you modify this you also want to modify - * systemdsystemunitpath= in systemd.pc.in! */ - generator_early, - persistent_config, - "/etc/systemd/system", - runtime_config, - "/run/systemd/system", - generator, - "/usr/local/lib/systemd/system", - SYSTEM_DATA_UNIT_PATH, - "/usr/lib/systemd/system", -#ifdef HAVE_SPLIT_USR - "/lib/systemd/system", -#endif - generator_late, - NULL); + break; + + case UNIT_FILE_USER: + add = user_dirs(persistent_config, runtime_config, + generator, generator_early, generator_late); + break; + + default: + assert_not_reached("Hmm, unexpected scope?"); + } if (!add) return -ENOMEM; @@ -520,19 +553,3 @@ void lookup_paths_free(LookupPaths *p) { p->generator_early = mfree(p->generator_early); p->generator_late = mfree(p->generator_late); } - -int lookup_paths_init_from_scope( - LookupPaths *p, - UnitFileScope scope, - const char *root_dir) { - - assert(p); - assert(scope >= 0); - assert(scope < _UNIT_FILE_SCOPE_MAX); - - return lookup_paths_init( - p, - scope == UNIT_FILE_SYSTEM ? MANAGER_SYSTEM : MANAGER_USER, - scope == UNIT_FILE_USER, - root_dir); -} diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index 64c8035c2b..974db79509 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -22,7 +22,6 @@ #include typedef struct LookupPaths LookupPaths; -typedef enum ManagerRunningAs ManagerRunningAs; #include "install.h" #include "macro.h" @@ -40,20 +39,12 @@ struct LookupPaths { char *generator_late; }; -enum ManagerRunningAs { - MANAGER_SYSTEM, - MANAGER_USER, - _MANAGER_RUNNING_AS_MAX, - _MANAGER_RUNNING_AS_INVALID = -1 -}; - int user_config_home(char **config_home); int user_runtime_dir(char **runtime_dir); -char **generator_paths(ManagerRunningAs running_as); +char **generator_paths(UnitFileScope scope); -int lookup_paths_init(LookupPaths *p, ManagerRunningAs running_as, bool personal, const char *root_dir); -int lookup_paths_init_from_scope(LookupPaths *p, UnitFileScope scope, const char *root_dir); +int lookup_paths_init(LookupPaths *p, UnitFileScope scope, const char *root_dir); void lookup_paths_free(LookupPaths *p); #define _cleanup_lookup_paths_free_ _cleanup_(lookup_paths_free) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index bab34986e3..3fd44a01d4 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -4810,7 +4810,7 @@ static int cat(int argc, char *argv[], void *userdata) { return -EINVAL; } - r = lookup_paths_init_from_scope(&lp, arg_scope, arg_root); + r = lookup_paths_init(&lp, arg_scope, arg_root); if (r < 0) return log_error_errno(r, "Failed to determine unit paths: %m"); @@ -5241,7 +5241,7 @@ static int enable_sysv_units(const char *verb, char **args) { /* Processes all SysV units, and reshuffles the array so that * afterwards only the native units remain */ - r = lookup_paths_init(&paths, MANAGER_SYSTEM, false, arg_root); + r = lookup_paths_init(&paths, arg_scope, arg_root); if (r < 0) return r; @@ -6074,7 +6074,7 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { assert(names); assert(paths); - r = lookup_paths_init_from_scope(&lp, arg_scope, arg_root); + r = lookup_paths_init(&lp, arg_scope, arg_root); if (r < 0) return r; diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c index b82c877dc7..3f5f24b4b9 100644 --- a/src/sysv-generator/sysv-generator.c +++ b/src/sysv-generator/sysv-generator.c @@ -1004,7 +1004,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = lookup_paths_init(&lp, MANAGER_SYSTEM, true, NULL); + r = lookup_paths_init(&lp, UNIT_FILE_SYSTEM, NULL); if (r < 0) { log_error_errno(r, "Failed to find lookup paths: %m"); goto finish; diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c index ad15075a5b..332755cf41 100644 --- a/src/test/test-cgroup-mask.c +++ b/src/test/test-cgroup-mask.c @@ -33,7 +33,7 @@ static int test_cgroup_mask(void) { /* Prepare the manager. */ assert_se(set_unit_path(TEST_DIR) >= 0); - r = manager_new(MANAGER_USER, true, &m); + r = manager_new(UNIT_FILE_USER, true, &m); if (r == -EPERM || r == -EACCES) { puts("manager_new: Permission denied. Skipping test."); return EXIT_TEST_SKIP; diff --git a/src/test/test-engine.c b/src/test/test-engine.c index ca66f5b684..52b34c03df 100644 --- a/src/test/test-engine.c +++ b/src/test/test-engine.c @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) { /* prepare the test */ assert_se(set_unit_path(TEST_DIR) >= 0); - r = manager_new(MANAGER_USER, true, &m); + r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return EXIT_TEST_SKIP; diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 901cc44af6..77ef4e8b2a 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -291,14 +291,14 @@ static void test_exec_spec_interpolation(Manager *m) { test(m, "exec-spec-interpolation.service", 0, CLD_EXITED); } -static int run_tests(ManagerRunningAs running_as, test_function_t *tests) { +static int run_tests(UnitFileScope scope, test_function_t *tests) { test_function_t *test = NULL; Manager *m = NULL; int r; assert_se(tests); - r = manager_new(running_as, true, &m); + r = manager_new(scope, true, &m); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return EXIT_TEST_SKIP; @@ -366,9 +366,9 @@ int main(int argc, char *argv[]) { assert_se(unsetenv("VAR2") == 0); assert_se(unsetenv("VAR3") == 0); - r = run_tests(MANAGER_USER, user_tests); + r = run_tests(UNIT_FILE_USER, user_tests); if (r != 0) return r; - return run_tests(MANAGER_SYSTEM, system_tests); + return run_tests(UNIT_FILE_SYSTEM, system_tests); } diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c index ebb11dcb6d..5575a364f2 100644 --- a/src/test/test-path-lookup.c +++ b/src/test/test-path-lookup.c @@ -26,7 +26,7 @@ #include "string-util.h" #include "strv.h" -static void test_paths(ManagerRunningAs running_as, bool personal) { +static void test_paths(UnitFileScope scope) { char template[] = "/tmp/test-path-lookup.XXXXXXX"; _cleanup_lookup_paths_free_ LookupPaths lp_without_env = {}; @@ -36,26 +36,26 @@ static void test_paths(ManagerRunningAs running_as, bool personal) { assert_se(mkdtemp(template)); assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0); - assert_se(lookup_paths_init(&lp_without_env, running_as, personal, NULL) == 0); + assert_se(lookup_paths_init(&lp_without_env, scope, NULL) == 0); assert_se(!strv_isempty(lp_without_env.search_path)); systemd_unit_path = strjoina(template, "/systemd-unit-path"); assert_se(setenv("SYSTEMD_UNIT_PATH", systemd_unit_path, 1) == 0); - assert_se(lookup_paths_init(&lp_with_env, running_as, personal, NULL) == 0); + assert_se(lookup_paths_init(&lp_with_env, scope, NULL) == 0); assert_se(strv_length(lp_with_env.search_path) == 1); assert_se(streq(lp_with_env.search_path[0], systemd_unit_path)); assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } -static void print_generator_paths(ManagerRunningAs running_as) { +static void print_generator_paths(UnitFileScope scope) { _cleanup_strv_free_ char **paths; char **dir; - log_info("Generators dirs (%s):", running_as == MANAGER_SYSTEM ? "system" : "user"); + log_info("Generators dirs (%s):", scope == UNIT_FILE_SYSTEM ? "system" : "user"); - paths = generator_paths(running_as); + paths = generator_paths(scope); STRV_FOREACH(dir, paths) log_info(" %s", *dir); } @@ -65,13 +65,12 @@ int main(int argc, char **argv) { log_parse_environment(); log_open(); - test_paths(MANAGER_SYSTEM, false); - test_paths(MANAGER_SYSTEM, true); - test_paths(MANAGER_USER, false); - test_paths(MANAGER_USER, true); + test_paths(UNIT_FILE_SYSTEM); + test_paths(UNIT_FILE_USER); + test_paths(UNIT_FILE_GLOBAL); - print_generator_paths(MANAGER_SYSTEM); - print_generator_paths(MANAGER_USER); + print_generator_paths(UNIT_FILE_SYSTEM); + print_generator_paths(UNIT_FILE_USER); return EXIT_SUCCESS; } diff --git a/src/test/test-path.c b/src/test/test-path.c index 1e704a03dc..e0c8db50ae 100644 --- a/src/test/test-path.c +++ b/src/test/test-path.c @@ -44,7 +44,7 @@ static int setup_test(Manager **m) { assert_se(m); - r = manager_new(MANAGER_USER, true, &tmp); + r = manager_new(UNIT_FILE_USER, true, &tmp); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return -EXIT_TEST_SKIP; diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c index 7f515b53d8..5083cd53c2 100644 --- a/src/test/test-sched-prio.c +++ b/src/test/test-sched-prio.c @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) { /* prepare the test */ assert_se(set_unit_path(TEST_DIR) >= 0); - r = manager_new(MANAGER_USER, true, &m); + r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return EXIT_TEST_SKIP; diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index cc6c61ba63..7f2fee772b 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -113,7 +113,7 @@ static void test_config_parse_exec(void) { Manager *m = NULL; Unit *u = NULL; - r = manager_new(MANAGER_USER, true, &m); + r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return; diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c index 3de94ef425..2fd83f321c 100644 --- a/src/test/test-unit-name.c +++ b/src/test/test-unit-name.c @@ -209,7 +209,7 @@ static int test_unit_printf(void) { assert_se(get_home_dir(&home) >= 0); assert_se(get_shell(&shell) >= 0); - r = manager_new(MANAGER_USER, true, &m); + r = manager_new(UNIT_FILE_USER, true, &m); if (r == -EPERM || r == -EACCES || r == -EADDRINUSE) { puts("manager_new: Permission denied. Skipping test."); return EXIT_TEST_SKIP; -- cgit v1.2.3-54-g00ecf From 2c289ea8332a2c0777d8940058ff7a6293f59b6c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Feb 2016 21:36:09 +0100 Subject: core: introduce MANAGER_IS_RELOADING() macro This replaces the old function call manager_is_reloading_or_reexecuting() which was used only at very few places. Use the new macro wherever we check whether we are reloading. This should hopefully make things a bit more readable, given the nature of Manager:n_reloading being a counter. --- src/core/job.c | 2 +- src/core/manager.c | 12 +++--------- src/core/manager.h | 4 ++-- src/core/scope.c | 6 +++--- src/core/service.c | 2 +- src/core/transaction.c | 2 +- src/core/unit.c | 12 ++++++------ 7 files changed, 17 insertions(+), 23 deletions(-) (limited to 'src/core') diff --git a/src/core/job.c b/src/core/job.c index 2e30431163..d9c5669c9f 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -137,7 +137,7 @@ void job_uninstall(Job *j) { /* Detach from next 'bigger' objects */ /* daemon-reload should be transparent to job observers */ - if (j->manager->n_reloading <= 0) + if (!MANAGER_IS_RELOADING(j->manager)) bus_job_send_removed_signal(j); *pj = NULL; diff --git a/src/core/manager.c b/src/core/manager.c index 1412d6718a..b3c3445f2c 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2115,7 +2115,7 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { /* Don't generate audit events if the service was already * started and we're just deserializing */ - if (m->n_reloading > 0) + if (MANAGER_IS_RELOADING(m)) return; if (u->type != UNIT_SERVICE) @@ -2149,7 +2149,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) { /* Don't generate plymouth events if the service was already * started and we're just deserializing */ - if (m->n_reloading > 0) + if (MANAGER_IS_RELOADING(m)) return; if (!MANAGER_IS_SYSTEM(m)) @@ -2572,12 +2572,6 @@ int manager_reload(Manager *m) { return r; } -bool manager_is_reloading_or_reexecuting(Manager *m) { - assert(m); - - return m->n_reloading != 0; -} - void manager_reset_failed(Manager *m) { Unit *u; Iterator i; @@ -2674,7 +2668,7 @@ static void manager_notify_finished(Manager *m) { void manager_check_finished(Manager *m) { assert(m); - if (m->n_reloading > 0) + if (MANAGER_IS_RELOADING(m)) return; /* Verify that we are actually running currently. Initially diff --git a/src/core/manager.h b/src/core/manager.h index 19eab958ea..17f84e6963 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -306,6 +306,8 @@ struct Manager { #define MANAGER_IS_SYSTEM(m) ((m)->unit_file_scope == UNIT_FILE_SYSTEM) #define MANAGER_IS_USER(m) ((m)->unit_file_scope != UNIT_FILE_SYSTEM) +#define MANAGER_IS_RELOADING(m) ((m)->n_reloading > 0) + int manager_new(UnitFileScope scope, bool test_run, Manager **m); Manager* manager_free(Manager *m); @@ -344,8 +346,6 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds); int manager_reload(Manager *m); -bool manager_is_reloading_or_reexecuting(Manager *m) _pure_; - void manager_reset_failed(Manager *m); void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success); diff --git a/src/core/scope.c b/src/core/scope.c index 361695c3f9..92a3aed331 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -138,7 +138,7 @@ static int scope_verify(Scope *s) { return 0; if (set_isempty(UNIT(s)->pids) && - !manager_is_reloading_or_reexecuting(UNIT(s)->manager) && + !MANAGER_IS_RELOADING(UNIT(s)->manager) && !unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) { log_unit_error(UNIT(s), "Scope has no PIDs. Refusing."); return -EINVAL; @@ -154,7 +154,7 @@ static int scope_load(Unit *u) { assert(s); assert(u->load_state == UNIT_STUB); - if (!u->transient && !manager_is_reloading_or_reexecuting(u->manager)) + if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) return -ENOENT; u->load_state = UNIT_LOADED; @@ -292,7 +292,7 @@ static int scope_start(Unit *u) { assert(s->state == SCOPE_DEAD); - if (!u->transient && !manager_is_reloading_or_reexecuting(u->manager)) + if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) return -ENOENT; (void) unit_realize_cgroup(u); diff --git a/src/core/service.c b/src/core/service.c index 7aea6f7ff4..58084e2f82 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -920,7 +920,7 @@ static void service_set_state(Service *s, ServiceState state) { /* For the inactive states unit_notify() will trim the cgroup, * but for exit we have to do that ourselves... */ - if (state == SERVICE_EXITED && UNIT(s)->manager->n_reloading <= 0) + if (state == SERVICE_EXITED && !MANAGER_IS_RELOADING(UNIT(s)->manager)) unit_prune_cgroup(UNIT(s)); /* For remain_after_exit services, let's see if we can "release" the diff --git a/src/core/transaction.c b/src/core/transaction.c index c894001cf9..dad387749c 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -855,7 +855,7 @@ int transaction_add_job_and_dependencies( * This matters when jobs are spawned as part of coldplugging itself (see e. g. path_coldplug()). * This way, we "recursively" coldplug units, ensuring that we do not look at state of * not-yet-coldplugged units. */ - if (unit->manager->n_reloading > 0) + if (MANAGER_IS_RELOADING(unit->manager)) unit_coldplug(unit); /* log_debug("Pulling in %s/%s from %s/%s", */ diff --git a/src/core/unit.c b/src/core/unit.c index fbc2b0d74d..565704851b 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -483,7 +483,7 @@ void unit_free(Unit *u) { assert(u); - if (u->manager->n_reloading <= 0) + if (!MANAGER_IS_RELOADING(u->manager)) unit_remove_transient(u); bus_unit_send_removed_signal(u); @@ -1834,7 +1834,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su m = u->manager; /* Update timestamps for state changes */ - if (m->n_reloading <= 0) { + if (!MANAGER_IS_RELOADING(m)) { dual_timestamp_get(&u->state_change_timestamp); if (UNIT_IS_INACTIVE_OR_FAILED(os) && !UNIT_IS_INACTIVE_OR_FAILED(ns)) @@ -1941,7 +1941,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su } else unexpected = true; - if (m->n_reloading <= 0) { + if (!MANAGER_IS_RELOADING(m)) { /* If this state change happened without being * requested by a job, then let's retroactively start @@ -1978,7 +1978,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su if (u->type == UNIT_SERVICE && !UNIT_IS_ACTIVE_OR_RELOADING(os) && - m->n_reloading <= 0) { + !MANAGER_IS_RELOADING(m)) { /* Write audit record if we have just finished starting up */ manager_send_unit_audit(m, u, AUDIT_SERVICE_START, true); u->in_audit = true; @@ -1995,7 +1995,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su if (u->type == UNIT_SERVICE && UNIT_IS_INACTIVE_OR_FAILED(ns) && !UNIT_IS_INACTIVE_OR_FAILED(os) && - m->n_reloading <= 0) { + !MANAGER_IS_RELOADING(m)) { /* Hmm, if there was no start record written * write it now, so that we always have a nice @@ -2016,7 +2016,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su manager_recheck_journal(m); unit_trigger_notify(u); - if (u->manager->n_reloading <= 0) { + if (!MANAGER_IS_RELOADING(u->manager)) { /* Maybe we finished startup and are now ready for * being stopped because unneeded? */ unit_check_unneeded(u); -- cgit v1.2.3-54-g00ecf From 92dd7c49659a0bb4c8e081199e4ff4351f37397a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Feb 2016 00:30:32 +0100 Subject: core: reuse manager_get_runtime_prefix() at more places --- src/core/manager.c | 19 +++++++------------ src/core/unit-printf.c | 11 +++-------- 2 files changed, 10 insertions(+), 20 deletions(-) (limited to 'src/core') diff --git a/src/core/manager.c b/src/core/manager.c index b3c3445f2c..c72b46be30 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -676,6 +676,7 @@ static int manager_setup_notify(Manager *m) { .sa.sa_family = AF_UNIX, }; static const int one = 1; + const char *e; /* First free all secondary fields */ m->notify_socket = mfree(m->notify_socket); @@ -687,19 +688,13 @@ static int manager_setup_notify(Manager *m) { fd_inc_rcvbuf(fd, NOTIFY_RCVBUF_SIZE); - if (MANAGER_IS_SYSTEM(m)) - m->notify_socket = strdup("/run/systemd/notify"); - else { - const char *e; - - e = getenv("XDG_RUNTIME_DIR"); - if (!e) { - log_error_errno(errno, "XDG_RUNTIME_DIR is not set: %m"); - return -EINVAL; - } - - m->notify_socket = strappend(e, "/systemd/notify"); + e = manager_get_runtime_prefix(m); + if (!e) { + log_error("Failed to determine runtime prefix."); + return -EINVAL; } + + m->notify_socket = strappend(e, "/systemd/notify"); if (!m->notify_socket) return log_oom(); diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c index 40da52fcac..f11df42af3 100644 --- a/src/core/unit-printf.c +++ b/src/core/unit-printf.c @@ -140,14 +140,9 @@ static int specifier_runtime(char specifier, void *data, void *userdata, char ** assert(u); - if (MANAGER_IS_SYSTEM(u->manager)) - e = "/run"; - else { - e = getenv("XDG_RUNTIME_DIR"); - if (!e) - return -EOPNOTSUPP; - } - + e = manager_get_runtime_prefix(u->manager); + if (!e) + return -EOPNOTSUPP; n = strdup(e); if (!n) return -ENOMEM; -- cgit v1.2.3-54-g00ecf From 39591351391de3ef2fd23cc5aea5bdd6ab712db6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Feb 2016 01:13:57 +0100 Subject: core: add a separate unit directory for transient units Previously, transient units were created below the normal runtime directory /run/systemd/system. With this change they are created in a special transient directory /run/systemd/transient, which only contains data for transient units. This clarifies the life-cycle of transient units, and makes clear they are distinct from user-provided runtime units. In particular, users may now extend transient units via /run/systemd/system, without systemd interfering with the life-cycle of these files. This change also adds code so that when a transient unit exits only the drop-ins in this new directory are removed, but nothing else. Fixes: #2139 --- src/core/manager.c | 6 +++++ src/core/unit.c | 62 ++++++++++++++++++++++------------------------ src/shared/path-lookup.c | 64 +++++++++++++++++++++++++++++++++++++++++++++--- src/shared/path-lookup.h | 3 +++ 4 files changed, 99 insertions(+), 36 deletions(-) (limited to 'src/core') diff --git a/src/core/manager.c b/src/core/manager.c index c72b46be30..1bc7921abe 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -63,6 +63,7 @@ #include "manager.h" #include "missing.h" #include "mkdir.h" +#include "mkdir.h" #include "parse-util.h" #include "path-lookup.h" #include "path-util.h" @@ -1108,6 +1109,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { if (r < 0) return r; + /* Make sure the transient directory always exists, so that it remains in the search path */ + r = mkdir_p_label(m->lookup_paths.transient, 0755); + if (r < 0) + return r; + dual_timestamp_get(&m->generators_start_timestamp); r = manager_run_generators(m); dual_timestamp_get(&m->generators_finish_timestamp); diff --git a/src/core/unit.c b/src/core/unit.c index 565704851b..f6c9891aad 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -418,13 +418,22 @@ static void unit_remove_transient(Unit *u) { (void) unlink(u->fragment_path); STRV_FOREACH(i, u->dropin_paths) { - _cleanup_free_ char *p = NULL; + _cleanup_free_ char *p = NULL, *pp = NULL; - (void) unlink(*i); + p = dirname_malloc(*i); /* Get the drop-in directory from the drop-in file */ + if (!p) + continue; + + pp = dirname_malloc(p); /* Get the config directory from the drop-in directory */ + if (!pp) + continue; + + /* Only drop transient drop-ins */ + if (!path_equal(u->manager->lookup_paths.transient, pp)) + continue; - p = dirname_malloc(*i); - if (p) - (void) rmdir(p); + (void) unlink(*i); + (void) rmdir(p); } } @@ -3315,35 +3324,24 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) { return *(ExecRuntime**) ((uint8_t*) u + offset); } -static int unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode, bool transient, char **dir) { +static const char* unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode) { assert(u); - if (MANAGER_IS_USER(u->manager)) { - int r; + if (u->transient) /* Redirect drop-ins for transient units always into the transient directory. */ + return u->manager->lookup_paths.transient; - if (mode == UNIT_PERSISTENT && !transient) - r = user_config_home(dir); - else - r = user_runtime_dir(dir); - if (r == 0) - return -ENOENT; + if (mode == UNIT_RUNTIME) + return u->manager->lookup_paths.runtime_config; - return r; - } + if (mode == UNIT_PERSISTENT) + return u->manager->lookup_paths.persistent_config; - if (mode == UNIT_PERSISTENT && !transient) - *dir = strdup("/etc/systemd/system"); - else - *dir = strdup("/run/systemd/system"); - if (!*dir) - return -ENOMEM; - - return 0; + return NULL; } int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) { - - _cleanup_free_ char *dir = NULL, *p = NULL, *q = NULL; + _cleanup_free_ char *p = NULL, *q = NULL; + const char *dir; int r; assert(u); @@ -3351,9 +3349,9 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; - r = unit_drop_in_dir(u, mode, u->transient, &dir); - if (r < 0) - return r; + dir = unit_drop_in_dir(u, mode); + if (!dir) + return -EINVAL; r = write_drop_in(dir, u->id, 50, name, data); if (r < 0) @@ -3398,7 +3396,7 @@ int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *n } int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) { - _cleanup_free_ char *ndata = NULL; + const char *ndata; assert(u); assert(name); @@ -3410,9 +3408,7 @@ int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char * if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; - ndata = strjoin("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL); - if (!ndata) - return -ENOMEM; + ndata = strjoina("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL); return unit_write_drop_in(u, mode, name, ndata); } diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index 11b9bb6107..f437de370c 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -111,7 +111,8 @@ static char** user_dirs( const char *runtime_config, const char *generator, const char *generator_early, - const char *generator_late) { + const char *generator_late, + const char *transient) { const char * const config_unit_paths[] = { USER_CONFIG_UNIT_PATH, @@ -172,6 +173,10 @@ static char** user_dirs( return NULL; /* Now merge everything we found. */ + if (transient) + if (strv_extend(&res, transient) < 0) + return NULL; + if (generator_early) if (strv_extend(&res, generator_early) < 0) return NULL; @@ -305,6 +310,42 @@ static int acquire_generator_dirs( return 0; } +static int acquire_transient_dir(UnitFileScope scope, char **ret) { + char *transient; + + assert(ret); + + switch (scope) { + + case UNIT_FILE_SYSTEM: + transient = strdup("/run/systemd/transient"); + break; + + case UNIT_FILE_USER: { + const char *e; + + e = getenv("XDG_RUNTIME_DIR"); + if (!e) + return -ENXIO; + + transient = strjoin(e, "/systemd/transient", NULL); + break; + } + + case UNIT_FILE_GLOBAL: + return -EOPNOTSUPP; + + default: + assert_not_reached("Hmm, unexpected scope value."); + } + + if (!transient) + return -ENOMEM; + + *ret = transient; + return 0; +} + static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **runtime) { _cleanup_free_ char *a = NULL, *b = NULL; int r; @@ -377,8 +418,9 @@ int lookup_paths_init( _cleanup_free_ char *root = NULL, + *persistent_config = NULL, *runtime_config = NULL, *generator = NULL, *generator_early = NULL, *generator_late = NULL, - *persistent_config = NULL, *runtime_config = NULL; + *transient = NULL; bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */ char **l = NULL; const char *e; @@ -411,6 +453,10 @@ int lookup_paths_init( if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO) return r; + r = acquire_transient_dir(scope, &transient); + if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO) + return r; + /* First priority is whatever has been passed to us via env * vars */ e = getenv("SYSTEMD_UNIT_PATH"); @@ -449,6 +495,7 @@ int lookup_paths_init( add = strv_new( /* If you modify this you also want to modify * systemdsystemunitpath= in systemd.pc.in! */ + STRV_IFNOTNULL(transient), STRV_IFNOTNULL(generator_early), persistent_config, SYSTEM_CONFIG_UNIT_PATH, @@ -471,6 +518,7 @@ int lookup_paths_init( /* If you modify this you also want to modify * systemduserunitpath= in systemd.pc.in, and * the arrays in user_dirs() above! */ + STRV_IFNOTNULL(transient), STRV_IFNOTNULL(generator_early), persistent_config, USER_CONFIG_UNIT_PATH, @@ -489,7 +537,8 @@ int lookup_paths_init( case UNIT_FILE_USER: add = user_dirs(persistent_config, runtime_config, - generator, generator_early, generator_late); + generator, generator_early, generator_late, + transient); break; default: @@ -526,6 +575,10 @@ int lookup_paths_init( if (r < 0) return r; + r = patch_root_prefix(&transient, root); + if (r < 0) + return r; + if (!path_strv_resolve_uniq(l, root)) return -ENOMEM; @@ -554,6 +607,9 @@ int lookup_paths_init( p->generator_late = generator_late; generator = generator_early = generator_late = NULL; + p->transient = transient; + transient = NULL; + p->root_dir = root; root = NULL; @@ -573,5 +629,7 @@ void lookup_paths_free(LookupPaths *p) { p->generator_early = mfree(p->generator_early); p->generator_late = mfree(p->generator_late); + p->transient = mfree(p->transient); + p->root_dir = mfree(p->root_dir); } diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index 078c3484f5..b0603c0c99 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -38,6 +38,9 @@ struct LookupPaths { char *generator_early; char *generator_late; + /* Where to place transient unit files */ + char *transient; + /* The root directory prepended to all items above, or NULL */ char *root_dir; }; -- cgit v1.2.3-54-g00ecf From cd64fd56134ef00cce0651e741d4ebda3791d97b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Feb 2016 01:44:30 +0100 Subject: path-lookup: split out logic for mkdir/rmdir of generator dirs in their own functions --- src/core/manager.c | 15 ++------------- src/shared/path-lookup.c | 37 +++++++++++++++++++++++++++++++++++-- src/shared/path-lookup.h | 3 +++ 3 files changed, 40 insertions(+), 15 deletions(-) (limited to 'src/core') diff --git a/src/core/manager.c b/src/core/manager.c index 1bc7921abe..d48b41d88f 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2737,15 +2737,7 @@ static int manager_run_generators(Manager *m) { return 0; found: - r = mkdir_p_label(m->lookup_paths.generator, 0755); - if (r < 0) - goto finish; - - r = mkdir_p_label(m->lookup_paths.generator_early, 0755); - if (r < 0) - goto finish; - - r = mkdir_p_label(m->lookup_paths.generator_late, 0755); + r = lookup_paths_mkdir_generator(&m->lookup_paths); if (r < 0) goto finish; @@ -2759,10 +2751,7 @@ static int manager_run_generators(Manager *m) { execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, (char**) argv); finish: - /* Trim empty dirs */ - (void) rmdir(m->lookup_paths.generator); - (void) rmdir(m->lookup_paths.generator_early); - (void) rmdir(m->lookup_paths.generator_late); + lookup_paths_trim_generator(&m->lookup_paths); return r; } diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index f437de370c..083e467475 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -26,6 +26,7 @@ #include "install.h" #include "log.h" #include "macro.h" +#include "mkdir.h" #include "path-lookup.h" #include "path-util.h" #include "stat-util.h" @@ -457,8 +458,7 @@ int lookup_paths_init( if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO) return r; - /* First priority is whatever has been passed to us via env - * vars */ + /* First priority is whatever has been passed to us via env vars */ e = getenv("SYSTEMD_UNIT_PATH"); if (e) { const char *k; @@ -633,3 +633,36 @@ void lookup_paths_free(LookupPaths *p) { p->root_dir = mfree(p->root_dir); } + +int lookup_paths_mkdir_generator(LookupPaths *p) { + int r, q; + + assert(p); + + r = mkdir_p_label(p->generator, 0755); + + q = mkdir_p_label(p->generator_early, 0755); + if (q < 0 && r >= 0) + r = q; + + q = mkdir_p_label(p->generator_late, 0755); + if (q < 0 && r >= 0) + r = q; + + return r; +} + +void lookup_paths_trim_generator(LookupPaths *p) { + assert(p); + + /* Trim empty dirs */ + + if (p->generator) + (void) rmdir(p->generator); + + if (p->generator_early) + (void) rmdir(p->generator_early); + + if (p->generator_late) + (void) rmdir(p->generator_late); +} diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index b0603c0c99..27be1d8be8 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -52,5 +52,8 @@ char **generator_paths(UnitFileScope scope); int lookup_paths_init(LookupPaths *p, UnitFileScope scope, const char *root_dir); +int lookup_paths_mkdir_generator(LookupPaths *p); +void lookup_paths_trim_generator(LookupPaths *p); + void lookup_paths_free(LookupPaths *p); #define _cleanup_lookup_paths_free_ _cleanup_(lookup_paths_free) -- cgit v1.2.3-54-g00ecf From a14533430498bfaa91ba19b7fd0268bd2ef7d797 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Feb 2016 02:32:19 +0100 Subject: core: rework logic to drop duplicate and non-existing items from search path Move this into a function of its own, so that we can run it after we ran the generators, so that it takes into account removed generator dirs. --- src/core/manager.c | 2 + src/shared/path-lookup.c | 107 +++++++++++++++++++++++++++++++++++++------- src/shared/path-lookup.h | 2 + src/test/test-path-lookup.c | 6 ++- 4 files changed, 100 insertions(+), 17 deletions(-) (limited to 'src/core') diff --git a/src/core/manager.c b/src/core/manager.c index d48b41d88f..55f2f49a06 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1120,6 +1120,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { if (r < 0) return r; + lookup_paths_reduce(&m->lookup_paths); manager_build_unit_path_cache(m); /* If we will deserialize make sure that during enumeration @@ -2540,6 +2541,7 @@ int manager_reload(Manager *m) { if (q < 0 && r >= 0) r = q; + lookup_paths_reduce(&m->lookup_paths); manager_build_unit_path_cache(m); /* First, enumerate what we can from all config files */ diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index 083e467475..eeabdd1ecd 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -412,6 +412,22 @@ static int patch_root_prefix(char **p, const char *root_dir) { return 0; } +static int patch_root_prefix_strv(char **l, const char *root_dir) { + char **i; + int r; + + if (!root_dir) + return 0; + + STRV_FOREACH(i, l) { + r = patch_root_prefix(i, root_dir); + if (r < 0) + return r; + } + + return 0; +} + int lookup_paths_init( LookupPaths *p, UnitFileScope scope, @@ -579,23 +595,11 @@ int lookup_paths_init( if (r < 0) return r; - if (!path_strv_resolve_uniq(l, root)) + r = patch_root_prefix_strv(l, root); + if (r < 0) return -ENOMEM; - if (strv_isempty(l)) { - log_debug("Ignoring unit files."); - l = strv_free(l); - } else { - _cleanup_free_ char *t; - - t = strv_join(l, "\n\t"); - if (!t) - return -ENOMEM; - - log_debug("Looking for unit files in (higher priority first):\n\t%s", t); - } - - p->search_path = l; + p->search_path = strv_uniq(l); l = NULL; p->persistent_config = persistent_config; @@ -634,6 +638,79 @@ void lookup_paths_free(LookupPaths *p) { p->root_dir = mfree(p->root_dir); } +int lookup_paths_reduce(LookupPaths *p) { + _cleanup_free_ struct stat *stats = NULL; + size_t n_stats = 0, allocated = 0; + unsigned c = 0; + int r; + + assert(p); + + /* Drop duplicates and non-existing directories from the search path. We figure out whether two directories are + * the same by comparing their device and inode numbers. Note one special tweak: when we have a root path set, + * we do not follow symlinks when retrieving them, because the kernel wouldn't take the root prefix into + * account when following symlinks. When we have no root path set this restriction does not apply however. */ + + if (!p->search_path) + return 0; + + while (p->search_path[c]) { + struct stat st; + unsigned k; + + if (p->root_dir) + r = lstat(p->search_path[c], &st); + else + r = stat(p->search_path[c], &st); + if (r < 0) { + if (errno == ENOENT) + goto remove_item; + + /* If something we don't grok happened, let's better leave it in. */ + log_debug_errno(errno, "Failed to stat %s: %m", p->search_path[c]); + c++; + continue; + } + + for (k = 0; k < n_stats; k++) { + if (stats[k].st_dev == st.st_dev && + stats[k].st_ino == st.st_ino) + break; + } + + if (k < n_stats) /* Is there already an entry with the same device/inode? */ + goto remove_item; + + if (!GREEDY_REALLOC(stats, allocated, n_stats+1)) + return -ENOMEM; + + stats[n_stats++] = st; + c++; + continue; + + remove_item: + free(p->search_path[c]); + memmove(p->search_path + c, + p->search_path + c + 1, + (strv_length(p->search_path + c + 1) + 1) * sizeof(char*)); + } + + if (strv_isempty(p->search_path)) { + log_debug("Ignoring unit files."); + p->search_path = strv_free(p->search_path); + } else { + _cleanup_free_ char *t; + + t = strv_join(p->search_path, "\n\t"); + if (!t) + return -ENOMEM; + + log_debug("Looking for unit files in (higher priority first):\n\t%s", t); + } + + return 0; +} + int lookup_paths_mkdir_generator(LookupPaths *p) { int r, q; diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index 27be1d8be8..5a5d734deb 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -52,6 +52,8 @@ char **generator_paths(UnitFileScope scope); int lookup_paths_init(LookupPaths *p, UnitFileScope scope, const char *root_dir); +int lookup_paths_reduce(LookupPaths *p); + int lookup_paths_mkdir_generator(LookupPaths *p); void lookup_paths_trim_generator(LookupPaths *p); diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c index 5575a364f2..5ee6f4ebb2 100644 --- a/src/test/test-path-lookup.c +++ b/src/test/test-path-lookup.c @@ -36,8 +36,8 @@ static void test_paths(UnitFileScope scope) { assert_se(mkdtemp(template)); assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0); - assert_se(lookup_paths_init(&lp_without_env, scope, NULL) == 0); - + assert_se(lookup_paths_init(&lp_without_env, scope, NULL) >= 0); + assert_se(lookup_paths_reduce(&lp_without_env) >= 0); assert_se(!strv_isempty(lp_without_env.search_path)); systemd_unit_path = strjoina(template, "/systemd-unit-path"); @@ -45,6 +45,8 @@ static void test_paths(UnitFileScope scope) { assert_se(lookup_paths_init(&lp_with_env, scope, NULL) == 0); assert_se(strv_length(lp_with_env.search_path) == 1); assert_se(streq(lp_with_env.search_path[0], systemd_unit_path)); + assert_se(lookup_paths_reduce(&lp_with_env) >= 0); + assert_se(strv_length(lp_with_env.search_path) == 0); assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } -- cgit v1.2.3-54-g00ecf From d7e0da1db2ac9e747893ef5f565c554eb246e3f4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Feb 2016 17:05:33 +0100 Subject: core: don't drop transient drop-ins when loading the rest Previously, when creating a transient unit, we'd first add the transient drop-ins to the unit, and then normally load any other drop-ins later on top of this, replacing the already loaded drop-ins. Let's not do this, after all the transient drop-ins area already in effect, let's just add what we find on disk, but not replace it. --- src/core/load-dropin.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c index 1c65055a3f..f83fa09301 100644 --- a/src/core/load-dropin.c +++ b/src/core/load-dropin.c @@ -44,6 +44,7 @@ static int add_dependency_consumer( } int unit_load_dropin(Unit *u) { + _cleanup_strv_free_ char **l = NULL; Iterator i; char *t, **f; int r; @@ -63,11 +64,19 @@ int unit_load_dropin(Unit *u) { } } - u->dropin_paths = strv_free(u->dropin_paths); - r = unit_find_dropin_paths(u, &u->dropin_paths); + r = unit_find_dropin_paths(u, &l); if (r <= 0) return 0; + if (!u->dropin_paths) { + u->dropin_paths = l; + l = NULL; + } else { + r = strv_extend_strv(&u->dropin_paths, l, true); + if (r < 0) + return log_oom(); + } + STRV_FOREACH(f, u->dropin_paths) { config_parse(u->id, *f, NULL, UNIT_VTABLE(u)->sections, -- cgit v1.2.3-54-g00ecf From 193dc81ee336ad07b92e7e945b458eb24f615f55 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Feb 2016 17:58:37 +0100 Subject: core: don't reorder drop-ins when changing properties The drop-in order we present should actually show what we is in effect, hence let's not reorder it when writing changes. After all, just sorting alphabetically is going to break things, as it doesn't respect that /etc breaks /run breaks /usr... --- src/core/unit.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core') diff --git a/src/core/unit.c b/src/core/unit.c index f6c9891aad..ac29353299 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3365,7 +3365,6 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co if (r < 0) return r; - strv_sort(u->dropin_paths); strv_uniq(u->dropin_paths); u->dropin_mtime = now(CLOCK_REALTIME); -- cgit v1.2.3-54-g00ecf From d063a527411ac9aa715bee59a9dcc59c877d2362 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Feb 2016 18:28:45 +0100 Subject: core: modernize manager_build_unit_patch_cache() a bit --- src/core/manager.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'src/core') diff --git a/src/core/manager.c b/src/core/manager.c index 55f2f49a06..b1f79e014e 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -49,6 +49,7 @@ #include "dbus-manager.h" #include "dbus-unit.h" #include "dbus.h" +#include "dirent-util.h" #include "env-util.h" #include "escape.h" #include "exit-status.h" @@ -1026,7 +1027,6 @@ static void manager_coldplug(Manager *m) { static void manager_build_unit_path_cache(Manager *m) { char **i; - _cleanup_closedir_ DIR *d = NULL; int r; assert(m); @@ -1035,29 +1035,27 @@ static void manager_build_unit_path_cache(Manager *m) { m->unit_path_cache = set_new(&string_hash_ops); if (!m->unit_path_cache) { - log_error("Failed to allocate unit path cache."); - return; + r = -ENOMEM; + goto fail; } /* This simply builds a list of files we know exist, so that * we don't always have to go to disk */ STRV_FOREACH(i, m->lookup_paths.search_path) { + _cleanup_closedir_ DIR *d = NULL; struct dirent *de; d = opendir(*i); if (!d) { if (errno != ENOENT) - log_error_errno(errno, "Failed to open directory %s: %m", *i); + log_warning_errno(errno, "Failed to open directory %s, ignoring: %m", *i); continue; } - while ((de = readdir(d))) { + FOREACH_DIRENT(de, d, r = -errno; goto fail) { char *p; - if (hidden_file(de->d_name)) - continue; - p = strjoin(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL); if (!p) { r = -ENOMEM; @@ -1068,20 +1066,15 @@ static void manager_build_unit_path_cache(Manager *m) { if (r < 0) goto fail; } - - d = safe_closedir(d); } return; fail: - log_error_errno(r, "Failed to build unit path cache: %m"); - - set_free_free(m->unit_path_cache); - m->unit_path_cache = NULL; + log_warning_errno(r, "Failed to build unit path cache, proceeding without: %m"); + m->unit_path_cache = set_free_free(m->unit_path_cache); } - static void manager_distribute_fds(Manager *m, FDSet *fds) { Iterator i; Unit *u; -- cgit v1.2.3-54-g00ecf From e4fca67ff02c44216780c5a61b1ab66cb6c09752 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 7 Mar 2016 19:07:30 +0100 Subject: install: introduce a new unit file state "transient" Now, that the search path logic knows the unit path for transient units we also can introduce an explicit unit file state "transient" that clarifies to the user what kind of unit file he is encountering. --- man/systemctl.xml | 5 +++++ src/core/dbus-manager.c | 4 ++-- src/shared/install.c | 32 ++++++++++++++++++++++++++++++++ src/shared/install.h | 1 + src/systemctl/systemctl.c | 4 ++-- 5 files changed, 42 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/man/systemctl.xml b/man/systemctl.xml index 0febdfd4de..064777810f 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1186,6 +1186,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service The unit file was generated dynamically via a generator tool. See systemd.generator7. Generated unit files may not be enabled, they are enabled implicitly by their generator. 0 + + transient + The unit file has been created dynamically with the runtime API. Transient units may not be enabled. + 0 + bad The unit file is invalid or another error occurred. Note that is-enabled will not actually return this state, but print an error message instead. However the unit file listing printed by list-unit-files might show it. diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 5fc3526751..f0ee2fcb36 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1641,7 +1641,7 @@ static int method_enable_unit_files_generic( if (r == -ESHUTDOWN) return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked."); if (r == -EADDRNOTAVAIL) - return sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, "Unit file is generated."); + return sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, "Unit file is transient or generated."); if (r < 0) return r; @@ -1866,7 +1866,7 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd if (r == -ESHUTDOWN) return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked."); if (r == -EADDRNOTAVAIL) - return sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, "Unit file is generated."); + return sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, "Unit file is transient or generated."); if (r < 0) return r; diff --git a/src/shared/install.c b/src/shared/install.c index 6c5d3ce7d1..c19c85a3b5 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -119,6 +119,19 @@ static int path_is_generator(const LookupPaths *p, const char *path) { path_equal(p->generator_late, parent); } +static int path_is_transient(const LookupPaths *p, const char *path) { + _cleanup_free_ char *parent = NULL; + + assert(p); + assert(path); + + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; + + return path_equal(p->transient, parent); +} + static int path_is_config(const LookupPaths *p, const char *path) { _cleanup_free_ char *parent = NULL; const char *rpath; @@ -1710,6 +1723,8 @@ int unit_file_add_dependency( return -ESHUTDOWN; if (path_is_generator(&paths, target_info->path)) return -EADDRNOTAVAIL; + if (path_is_transient(&paths, target_info->path)) + return -EADDRNOTAVAIL; assert(target_info->type == UNIT_FILE_TYPE_REGULAR); @@ -1723,6 +1738,8 @@ int unit_file_add_dependency( return -ESHUTDOWN; if (path_is_generator(&paths, i->path)) return -EADDRNOTAVAIL; + if (path_is_transient(&paths, i->path)) + return -EADDRNOTAVAIL; assert(i->type == UNIT_FILE_TYPE_REGULAR); @@ -1777,6 +1794,8 @@ int unit_file_enable( return -ESHUTDOWN; if (path_is_generator(&paths, i->path)) return -EADDRNOTAVAIL; + if (path_is_transient(&paths, i->path)) + return -EADDRNOTAVAIL; assert(i->type == UNIT_FILE_TYPE_REGULAR); } @@ -1891,6 +1910,8 @@ int unit_file_set_default( return -ESHUTDOWN; if (path_is_generator(&paths, i->path)) return -EADDRNOTAVAIL; + if (path_is_transient(&paths, i->path)) + return -EADDRNOTAVAIL; old_path = skip_root(&paths, i->path); new_path = strjoina(paths.persistent_config, "/" SPECIAL_DEFAULT_TARGET); @@ -1975,6 +1996,14 @@ int unit_file_lookup_state( break; } + r = path_is_transient(paths, i->path); + if (r < 0) + return r; + if (r > 0) { + state = UNIT_FILE_TRANSIENT; + break; + } + r = find_symlinks_in_scope(scope, paths, i->name, &state); if (r < 0) return r; @@ -2176,6 +2205,8 @@ static int preset_prepare_one( return -ESHUTDOWN; if (path_is_generator(paths, i->path)) return -EADDRNOTAVAIL; + if (path_is_transient(paths, i->path)) + return -EADDRNOTAVAIL; } else r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); @@ -2372,6 +2403,7 @@ static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = { [UNIT_FILE_DISABLED] = "disabled", [UNIT_FILE_INDIRECT] = "indirect", [UNIT_FILE_GENERATED] = "generated", + [UNIT_FILE_TRANSIENT] = "transient", [UNIT_FILE_BAD] = "bad", }; diff --git a/src/shared/install.h b/src/shared/install.h index 9c33110e44..578664dd48 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -55,6 +55,7 @@ enum UnitFileState { UNIT_FILE_DISABLED, UNIT_FILE_INDIRECT, UNIT_FILE_GENERATED, + UNIT_FILE_TRANSIENT, UNIT_FILE_BAD, _UNIT_FILE_STATE_MAX, _UNIT_FILE_STATE_INVALID = -1 diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 3fd44a01d4..b64a97375e 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5444,7 +5444,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) { if (r == -ESHUTDOWN) return log_error_errno(r, "Unit file is masked."); if (r == -EADDRNOTAVAIL) - return log_error_errno(r, "Unit file is generated."); + return log_error_errno(r, "Unit file is transient or generated."); if (r < 0) return log_error_errno(r, "Operation failed: %m"); @@ -5612,7 +5612,7 @@ static int add_dependency(int argc, char *argv[], void *userdata) { if (r == -ESHUTDOWN) return log_error_errno(r, "Unit file is masked."); if (r == -EADDRNOTAVAIL) - return log_error_errno(r, "Unit file is generated."); + return log_error_errno(r, "Unit file is transient or generated."); if (r < 0) return log_error_errno(r, "Can't add dependency: %m"); -- cgit v1.2.3-54-g00ecf From d8d410f4455238e30daa1775b469e31f34371f87 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Apr 2016 20:46:52 +0200 Subject: core: minor coding style fix --- src/core/dbus-execute.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 973a60187d..9dfca14914 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -837,9 +837,9 @@ int bus_exec_context_set_transient_property( if (mode != UNIT_CHECK) { - if (isempty(uu)) { + if (isempty(uu)) c->user = mfree(c->user); - } else { + else { char *t; t = strdup(uu); @@ -864,9 +864,9 @@ int bus_exec_context_set_transient_property( if (mode != UNIT_CHECK) { - if (isempty(gg)) { + if (isempty(gg)) c->group = mfree(c->group); - } else { + else { char *t; t = strdup(gg); -- cgit v1.2.3-54-g00ecf From 07a7864324e146662cb06f49fc3cd666788e2e2f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Apr 2016 20:47:44 +0200 Subject: core: move flushing of generated unit files to path-lookup.c It's very similar to the mkdir and trim operations for the generator dirs, hence let's unify this at a single place. --- src/core/manager.c | 16 ++-------------- src/shared/path-lookup.c | 11 +++++++++++ src/shared/path-lookup.h | 1 + 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src/core') diff --git a/src/core/manager.c b/src/core/manager.c index b1f79e014e..6ce3e404c9 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -100,7 +100,6 @@ static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32 static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata); static int manager_dispatch_run_queue(sd_event_source *source, void *userdata); static int manager_run_generators(Manager *m); -static void manager_undo_generators(Manager *m); static void manager_watch_jobs_in_progress(Manager *m) { usec_t next; @@ -930,7 +929,7 @@ Manager* manager_free(Manager *m) { * around */ manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE); - manager_undo_generators(m); + lookup_paths_flush_generator(&m->lookup_paths); bus_done(m); @@ -2522,7 +2521,7 @@ int manager_reload(Manager *m) { /* From here on there is no way back. */ manager_clear_jobs_and_units(m); - manager_undo_generators(m); + lookup_paths_flush_generator(&m->lookup_paths); lookup_paths_free(&m->lookup_paths); q = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, NULL); @@ -2750,17 +2749,6 @@ finish: return r; } -static void manager_undo_generators(Manager *m) { - assert(m); - - if (m->lookup_paths.generator) - (void) rm_rf(m->lookup_paths.generator, REMOVE_ROOT); - if (m->lookup_paths.generator_early) - (void) rm_rf(m->lookup_paths.generator_early, REMOVE_ROOT); - if (m->lookup_paths.generator_late) - (void) rm_rf(m->lookup_paths.generator_late, REMOVE_ROOT); -} - int manager_environment_add(Manager *m, char **minus, char **plus) { char **a = NULL, **b = NULL, **l; assert(m); diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index 0735e3b4f5..685ae895d2 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -726,3 +726,14 @@ void lookup_paths_trim_generator(LookupPaths *p) { if (p->generator_late) (void) rmdir(p->generator_late); } + +void lookup_paths_flush_generator(LookupPaths *p) { + assert(p); + + if (p->generator) + (void) rm_rf(p->generator, REMOVE_ROOT); + if (p->generator_early) + (void) rm_rf(p->generator_early, REMOVE_ROOT); + if (p->generator_late) + (void) rm_rf(p->generator_late, REMOVE_ROOT); +} diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index 03f103dcc0..d151347a1b 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -53,6 +53,7 @@ int lookup_paths_reduce(LookupPaths *p); int lookup_paths_mkdir_generator(LookupPaths *p); void lookup_paths_trim_generator(LookupPaths *p); +void lookup_paths_flush_generator(LookupPaths *p); void lookup_paths_free(LookupPaths *p); #define _cleanup_lookup_paths_free_ _cleanup_(lookup_paths_free) -- cgit v1.2.3-54-g00ecf From 9183df707bde9e83d838e7b5a05db0c5f4b55e6d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Apr 2016 20:48:58 +0200 Subject: install: rename generator_paths() → generator_binary_paths() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is too confusing, as this funciton returns the paths to the generator binaries, while usually when we refer to the just the "generator path" we mean the generated unit files. Let's clean this up. --- src/core/manager.c | 2 +- src/shared/path-lookup.c | 2 +- src/shared/path-lookup.h | 2 +- src/test/test-path-lookup.c | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/manager.c b/src/core/manager.c index 6ce3e404c9..91fe9c2d5b 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2715,7 +2715,7 @@ static int manager_run_generators(Manager *m) { if (m->test_run) return 0; - paths = generator_paths(m->unit_file_scope); + paths = generator_binary_paths(m->unit_file_scope); if (!paths) return log_oom(); diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index 685ae895d2..d3d4243ad4 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -221,7 +221,7 @@ static char** user_dirs( return tmp; } -char **generator_paths(UnitFileScope scope) { +char **generator_binary_paths(UnitFileScope scope) { switch (scope) { diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index d151347a1b..29f74cf211 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -45,7 +45,7 @@ struct LookupPaths { char *root_dir; }; -char **generator_paths(UnitFileScope scope); +char **generator_binary_paths(UnitFileScope scope); int lookup_paths_init(LookupPaths *p, UnitFileScope scope, const char *root_dir); diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c index 6ef0535ecb..ba60482867 100644 --- a/src/test/test-path-lookup.c +++ b/src/test/test-path-lookup.c @@ -51,13 +51,13 @@ static void test_paths(UnitFileScope scope) { assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } -static void print_generator_paths(UnitFileScope scope) { +static void print_generator_binary_paths(UnitFileScope scope) { _cleanup_strv_free_ char **paths; char **dir; log_info("Generators dirs (%s):", scope == UNIT_FILE_SYSTEM ? "system" : "user"); - paths = generator_paths(scope); + paths = generator_binary_paths(scope); STRV_FOREACH(dir, paths) log_info(" %s", *dir); } @@ -71,8 +71,8 @@ int main(int argc, char **argv) { test_paths(UNIT_FILE_USER); test_paths(UNIT_FILE_GLOBAL); - print_generator_paths(UNIT_FILE_SYSTEM); - print_generator_paths(UNIT_FILE_USER); + print_generator_binary_paths(UNIT_FILE_SYSTEM); + print_generator_binary_paths(UNIT_FILE_USER); return EXIT_SUCCESS; } -- cgit v1.2.3-54-g00ecf From 4f4afc88ecd8ab9cfe9e1eeea7e3aeb937811937 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 7 Apr 2016 15:43:59 +0200 Subject: core: rework how transient unit files and property drop-ins work With this change the logic for placing transient unit files and drop-ins generated via "systemctl set-property" is reworked. The latter are now placed in the newly introduced "control" unit file directory. The fomer are now placed in the "transient" unit file directory. Note that the properties originally set when a transient unit was created will be written to and stay in the transient unit file directory, while later changes are done via drop-ins. This is preparation for a later "systemctl revert" addition, where existing drop-ins are flushed out, but the original transient definition is restored. --- src/basic/strv.c | 36 +++++++++++++++++++++++++++++++++ src/basic/strv.h | 1 + src/core/scope.c | 25 ++++++++++++----------- src/core/slice.c | 1 + src/core/unit.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++------ src/core/unit.h | 3 +++ 6 files changed, 109 insertions(+), 18 deletions(-) (limited to 'src/core') diff --git a/src/basic/strv.c b/src/basic/strv.c index 8282298dca..97a96e5762 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -558,6 +558,42 @@ int strv_extend(char ***l, const char *value) { return strv_consume(l, v); } +int strv_extend_front(char ***l, const char *value) { + size_t n, m; + char *v, **c; + + assert(l); + + /* Like strv_extend(), but prepends rather than appends the new entry */ + + if (!value) + return 0; + + n = strv_length(*l); + + /* Increase and overflow check. */ + m = n + 2; + if (m < n) + return -ENOMEM; + + v = strdup(value); + if (!v) + return -ENOMEM; + + c = realloc_multiply(*l, sizeof(char*), m); + if (!c) { + free(v); + return -ENOMEM; + } + + memmove(c+1, c, n * sizeof(char*)); + c[0] = v; + c[n+1] = NULL; + + *l = c; + return 0; +} + char **strv_uniq(char **l) { char **i; diff --git a/src/basic/strv.h b/src/basic/strv.h index 7bfa54408d..f61bbb5386 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -50,6 +50,7 @@ int strv_extend_strv(char ***a, char **b, bool filter_duplicates); int strv_extend_strv_concat(char ***a, char **b, const char *suffix); int strv_extend(char ***l, const char *value); int strv_extendf(char ***l, const char *format, ...) _printf_(2,0); +int strv_extend_front(char ***l, const char *value); int strv_push(char ***l, char *value); int strv_push_pair(char ***l, char *a, char *b); int strv_push_prepend(char ***l, char *value); diff --git a/src/core/scope.c b/src/core/scope.c index 92a3aed331..7078d1f7e9 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -155,25 +155,26 @@ static int scope_load(Unit *u) { assert(u->load_state == UNIT_STUB); if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) + /* Refuse to load non-transient scope units, but allow them while reloading. */ return -ENOENT; - u->load_state = UNIT_LOADED; - - r = unit_load_dropin(u); + r = unit_load_fragment_and_dropin_optional(u); if (r < 0) return r; - r = unit_patch_contexts(u); - if (r < 0) - return r; + if (u->load_state == UNIT_LOADED) { + r = unit_patch_contexts(u); + if (r < 0) + return r; - r = unit_set_default_slice(u); - if (r < 0) - return r; + r = unit_set_default_slice(u); + if (r < 0) + return r; - r = scope_add_default_dependencies(s); - if (r < 0) - return r; + r = scope_add_default_dependencies(s); + if (r < 0) + return r; + } return scope_verify(s); } diff --git a/src/core/slice.c b/src/core/slice.c index 667f61bde5..63a77c9bca 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -135,6 +135,7 @@ static int slice_load(Unit *u) { int r; assert(s); + assert(u->load_state == UNIT_STUB); r = unit_load_fragment_and_dropin_optional(u); if (r < 0) diff --git a/src/core/unit.c b/src/core/unit.c index ac29353299..c028f57f13 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -52,6 +52,7 @@ #include "stdio-util.h" #include "string-util.h" #include "strv.h" +#include "umask-util.h" #include "unit-name.h" #include "unit.h" #include "user-util.h" @@ -492,6 +493,9 @@ void unit_free(Unit *u) { assert(u); + if (u->transient_file) + fclose(u->transient_file); + if (!MANAGER_IS_RELOADING(u->manager)) unit_remove_transient(u); @@ -1231,6 +1235,15 @@ int unit_load(Unit *u) { if (u->load_state != UNIT_STUB) return 0; + if (u->transient_file) { + r = fflush_and_check(u->transient_file); + if (r < 0) + goto fail; + + fclose(u->transient_file); + u->transient_file = NULL; + } + if (UNIT_VTABLE(u)->load) { r = UNIT_VTABLE(u)->load(u); if (r < 0) @@ -3327,14 +3340,17 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) { static const char* unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode) { assert(u); + if (!IN_SET(mode, UNIT_RUNTIME, UNIT_PERSISTENT)) + return NULL; + if (u->transient) /* Redirect drop-ins for transient units always into the transient directory. */ return u->manager->lookup_paths.transient; if (mode == UNIT_RUNTIME) - return u->manager->lookup_paths.runtime_config; + return u->manager->lookup_paths.runtime_control; if (mode == UNIT_PERSISTENT) - return u->manager->lookup_paths.persistent_config; + return u->manager->lookup_paths.persistent_control; return NULL; } @@ -3346,6 +3362,13 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co assert(u); + if (u->transient_file) { + /* When this is a transient unit file in creation, then let's not create a new drop-in but instead + * write to the transient unit file. */ + fputs(data, u->transient_file); + return 0; + } + if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; @@ -3435,24 +3458,50 @@ int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const } int unit_make_transient(Unit *u) { + FILE *f; + char *path; + assert(u); if (!UNIT_VTABLE(u)->can_transient) return -EOPNOTSUPP; - u->load_state = UNIT_STUB; - u->load_error = 0; - u->transient = true; + path = strjoin(u->manager->lookup_paths.transient, "/", u->id, NULL); + if (!path) + return -ENOMEM; + + /* Let's open the file we'll write the transient settings into. This file is kept open as long as we are + * creating the transient, and is closed in unit_load(), as soon as we start loading the file. */ + + RUN_WITH_UMASK(0022) + f = fopen(path, "we"); + if (!f) { + free(path); + return -errno; + } + + if (u->transient_file) + fclose(u->transient_file); + u->transient_file = f; + + free(u->fragment_path); + u->fragment_path = path; - u->fragment_path = mfree(u->fragment_path); u->source_path = mfree(u->source_path); u->dropin_paths = strv_free(u->dropin_paths); u->fragment_mtime = u->source_mtime = u->dropin_mtime = 0; + u->load_state = UNIT_STUB; + u->load_error = 0; + u->transient = true; + unit_add_to_dbus_queue(u); unit_add_to_gc_queue(u); unit_add_to_load_queue(u); + fputs("# This is a transient unit file, created programmatically via the systemd API. Do not edit.\n", + u->transient_file); + return 0; } diff --git a/src/core/unit.h b/src/core/unit.h index 601e763ce2..cfdac852a5 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -95,6 +95,9 @@ struct Unit { usec_t source_mtime; usec_t dropin_mtime; + /* If this is a transient unit we are currently writing, this is where we are writing it to */ + FILE *transient_file; + /* If there is something to do with this unit, then this is the installed job for it */ Job *job; -- cgit v1.2.3-54-g00ecf From 8612da973d30c5a9530fa1b6b3d449147b5a3324 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 7 Apr 2016 16:15:26 +0200 Subject: core: be more paranoid when mixing umask and fopen() Let's be extra careful with the umask when we use simple fopen(), as this creates files with 0777 by default. --- src/basic/util.c | 4 +++- src/core/machine-id-setup.c | 3 +-- src/core/main.c | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/basic/util.c b/src/basic/util.c index f1e3bd5b48..6996527ec4 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -55,6 +55,7 @@ #include "string-util.h" #include "strv.h" #include "time-util.h" +#include "umask-util.h" #include "user-util.h" #include "util.h" @@ -781,7 +782,8 @@ int update_reboot_param_file(const char *param) { int r = 0; if (param) { - r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE); + RUN_WITH_UMASK(0022) + r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE); if (r < 0) return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m"); } else diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c index 7b25349c07..86da16c31e 100644 --- a/src/core/machine-id-setup.c +++ b/src/core/machine-id-setup.c @@ -259,9 +259,8 @@ int machine_id_setup(const char *root, sd_id128_t machine_id) { /* Hmm, we couldn't write it? So let's write it to * /run/machine-id as a replacement */ - RUN_WITH_UMASK(0022) { + RUN_WITH_UMASK(0022) r = write_string_file(run_machine_id, id, WRITE_STRING_FILE_CREATE); - } if (r < 0) { (void) unlink(run_machine_id); return log_error_errno(r, "Cannot write %s: %m", run_machine_id); diff --git a/src/core/main.c b/src/core/main.c index a428e345e0..2912608435 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -81,6 +81,7 @@ #include "strv.h" #include "switch-root.h" #include "terminal-util.h" +#include "umask-util.h" #include "user-util.h" #include "virt.h" #include "watchdog.h" @@ -1237,7 +1238,8 @@ static int write_container_id(void) { if (isempty(c)) return 0; - r = write_string_file("/run/systemd/container", c, WRITE_STRING_FILE_CREATE); + RUN_WITH_UMASK(0022) + r = write_string_file("/run/systemd/container", c, WRITE_STRING_FILE_CREATE); if (r < 0) return log_warning_errno(r, "Failed to write /run/systemd/container, ignoring: %m"); -- cgit v1.2.3-54-g00ecf From 27c06cb516c3b87c34f2a1c2c227152997d05c8c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 7 Apr 2016 16:53:37 +0200 Subject: core: rework reboot parameter logic a bit Always warn if something fails, and clarify that the involved utility functions do so in their name. Drop the REBOOT_PARAM_FILE macro. We don't do this for other flag file paths like this, so don't do this for this one either. The path isn't configurable anyway, hence let's make this easier to read by avoiding this one indirection. --- src/basic/def.h | 2 -- src/basic/util.c | 26 +++++++++++++++++--------- src/basic/util.h | 2 +- src/core/failure-action.c | 14 +++++++------- src/core/shutdown.c | 7 ++++++- src/systemctl/systemctl.c | 12 +++++++++--- 6 files changed, 40 insertions(+), 23 deletions(-) (limited to 'src/core') diff --git a/src/basic/def.h b/src/basic/def.h index 963343eb7d..1a7a0f4928 100644 --- a/src/basic/def.h +++ b/src/basic/def.h @@ -41,8 +41,6 @@ #define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT #define SIGNALS_IGNORE SIGPIPE -#define REBOOT_PARAM_FILE "/run/systemd/reboot-param" - #ifdef HAVE_SPLIT_USR #define KBD_KEYMAP_DIRS \ "/usr/share/keymaps/\0" \ diff --git a/src/basic/util.c b/src/basic/util.c index 6996527ec4..957b0e1ff1 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -778,16 +778,24 @@ uint64_t physical_memory(void) { return (uint64_t) mem * (uint64_t) page_size(); } -int update_reboot_param_file(const char *param) { - int r = 0; +int update_reboot_parameter_and_warn(const char *param) { + int r; - if (param) { - RUN_WITH_UMASK(0022) - r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE); - if (r < 0) - return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m"); - } else - (void) unlink(REBOOT_PARAM_FILE); + if (isempty(param)) { + if (unlink("/run/systemd/reboot-param") < 0) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m"); + } + + return 0; + } + + RUN_WITH_UMASK(0022) + r = write_string_file("/run/systemd/reboot-param", param, WRITE_STRING_FILE_CREATE); + if (r < 0) + return log_warning_errno(r, "Failed to write reboot parameter file: %m"); return 0; } diff --git a/src/basic/util.h b/src/basic/util.h index 286db05159..1c032c15c9 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -184,6 +184,6 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int uint64_t physical_memory(void); -int update_reboot_param_file(const char *param); +int update_reboot_parameter_and_warn(const char *param); int version(void); diff --git a/src/core/failure-action.c b/src/core/failure-action.c index d4aae4b6e7..ddae46190f 100644 --- a/src/core/failure-action.c +++ b/src/core/failure-action.c @@ -61,17 +61,17 @@ int failure_action( case FAILURE_ACTION_REBOOT: log_and_status(m, "Rebooting as result of failure."); - update_reboot_param_file(reboot_arg); - (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, - JOB_REPLACE_IRREVERSIBLY, NULL); + (void) update_reboot_parameter_and_warn(reboot_arg); + (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); break; case FAILURE_ACTION_REBOOT_FORCE: log_and_status(m, "Forcibly rebooting as result of failure."); - update_reboot_param_file(reboot_arg); + (void) update_reboot_parameter_and_warn(reboot_arg); m->exit_code = MANAGER_REBOOT; + break; case FAILURE_ACTION_REBOOT_IMMEDIATE: @@ -79,9 +79,10 @@ int failure_action( sync(); - if (reboot_arg) { + if (!isempty(reboot_arg)) { log_info("Rebooting with argument '%s'.", reboot_arg); syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, reboot_arg); + log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m"); } log_info("Rebooting."); @@ -90,8 +91,7 @@ int failure_action( case FAILURE_ACTION_POWEROFF: log_and_status(m, "Powering off as result of failure."); - (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, - JOB_REPLACE_IRREVERSIBLY, NULL); + (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); break; case FAILURE_ACTION_POWEROFF_FORCE: diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 96679c920f..e14755d84e 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -397,9 +397,14 @@ int main(int argc, char *argv[]) { if (!in_container) { _cleanup_free_ char *param = NULL; - if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) { + r = read_one_line_file("/run/systemd/reboot-param", ¶m); + if (r < 0) + log_warning_errno(r, "Failed to read reboot parameter file: %m"); + + if (!isempty(param)) { log_info("Rebooting with argument '%s'.", param); syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param); + log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m"); } } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index b64a97375e..b1c4a84eff 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3136,7 +3136,7 @@ static int start_special(int argc, char *argv[], void *userdata) { return r; if (a == ACTION_REBOOT && argc > 1) { - r = update_reboot_param_file(argv[1]); + r = update_reboot_parameter_and_warn(argv[1]); if (r < 0) return r; @@ -6949,7 +6949,7 @@ static int halt_parse_argv(int argc, char *argv[]) { } if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) { - r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL); + r = update_reboot_parameter_and_warn(argc == optind + 1 ? argv[optind] : NULL); if (r < 0) return r; } else if (optind < argc) { @@ -7450,6 +7450,7 @@ static int start_with_fallback(void) { } static int halt_now(enum action a) { + int r; /* The kernel will automaticall flush ATA disks and suchlike * on reboot(), but the file systems need to be synce'd @@ -7476,9 +7477,14 @@ static int halt_now(enum action a) { case ACTION_REBOOT: { _cleanup_free_ char *param = NULL; - if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) { + r = read_one_line_file("/run/systemd/reboot-param", ¶m); + if (r < 0) + log_warning_errno(r, "Failed to read reboot parameter file: %m"); + + if (!isempty(param)) { log_info("Rebooting with argument '%s'.", param); (void) syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param); + log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m"); } log_info("Rebooting."); -- cgit v1.2.3-54-g00ecf From 4943d14306c3e456525fdb793e7f48efea5b9236 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 7 Apr 2016 18:48:01 +0200 Subject: systemctl: don't confuse sysv code with generated units The SysV compat code checks whether there's a native unit file before looking for a SysV init script. Since the newest rework generated units will show up in the unit path, and hence the checks ended up assuming that there always was a native unit file for each init script: the generated one. With this change the generated unit file directory is suppressed from the search path when this check is done, to avoid the confusion. --- src/core/manager.c | 4 ++-- src/shared/install.c | 24 ++++++++++++------------ src/shared/path-lookup.c | 14 +++++++++----- src/shared/path-lookup.h | 6 +++++- src/systemctl/systemctl.c | 6 +++--- src/sysv-generator/sysv-generator.c | 2 +- src/test/test-path-lookup.c | 4 ++-- 7 files changed, 34 insertions(+), 26 deletions(-) (limited to 'src/core') diff --git a/src/core/manager.c b/src/core/manager.c index 91fe9c2d5b..5601770670 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1097,7 +1097,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { assert(m); - r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, NULL); + r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL); if (r < 0) return r; @@ -2524,7 +2524,7 @@ int manager_reload(Manager *m) { lookup_paths_flush_generator(&m->lookup_paths); lookup_paths_free(&m->lookup_paths); - q = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, NULL); + q = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL); if (q < 0 && r >= 0) r = q; diff --git a/src/shared/install.c b/src/shared/install.c index b5453adeee..7497a39219 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1507,7 +1507,7 @@ int unit_file_mask( assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -1554,7 +1554,7 @@ int unit_file_unmask( assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -1636,7 +1636,7 @@ int unit_file_link( assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -1727,7 +1727,7 @@ int unit_file_add_dependency( if (!unit_name_is_valid(target, UNIT_NAME_ANY)) return -EINVAL; - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -1791,7 +1791,7 @@ int unit_file_enable( assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -1834,7 +1834,7 @@ int unit_file_disable( assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -1907,7 +1907,7 @@ int unit_file_set_default( if (streq(name, SPECIAL_DEFAULT_TARGET)) return -EINVAL; - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -1939,7 +1939,7 @@ int unit_file_get_default( assert(scope < _UNIT_FILE_SCOPE_MAX); assert(name); - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -2045,7 +2045,7 @@ int unit_file_get_state( assert(scope < _UNIT_FILE_SCOPE_MAX); assert(name); - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -2255,7 +2255,7 @@ int unit_file_preset( assert(scope < _UNIT_FILE_SCOPE_MAX); assert(mode < _UNIT_FILE_PRESET_MAX); - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -2292,7 +2292,7 @@ int unit_file_preset_all( assert(scope < _UNIT_FILE_SCOPE_MAX); assert(mode < _UNIT_FILE_PRESET_MAX); - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; @@ -2361,7 +2361,7 @@ int unit_file_get_list( assert(scope < _UNIT_FILE_SCOPE_MAX); assert(h); - r = lookup_paths_init(&paths, scope, root_dir); + r = lookup_paths_init(&paths, scope, 0, root_dir); if (r < 0) return r; diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index 1c8e22eee7..ca69a0aef2 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -441,6 +441,7 @@ static int patch_root_prefix_strv(char **l, const char *root_dir) { int lookup_paths_init( LookupPaths *p, UnitFileScope scope, + LookupPathsFlags flags, const char *root_dir) { _cleanup_free_ char @@ -477,9 +478,11 @@ int lookup_paths_init( if (r < 0 && r != -ENXIO) return r; - r = acquire_generator_dirs(scope, &generator, &generator_early, &generator_late); - if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO) - return r; + if ((flags & LOOKUP_PATHS_EXCLUDE_GENERATED) == 0) { + r = acquire_generator_dirs(scope, &generator, &generator_early, &generator_late); + if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO) + return r; + } r = acquire_transient_dir(scope, &transient); if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO) @@ -751,6 +754,9 @@ int lookup_paths_mkdir_generator(LookupPaths *p) { assert(p); + if (!p->generator || !p->generator_early || !p->generator_late) + return -EINVAL; + r = mkdir_p_label(p->generator, 0755); q = mkdir_p_label(p->generator_early, 0755); @@ -771,10 +777,8 @@ void lookup_paths_trim_generator(LookupPaths *p) { if (p->generator) (void) rmdir(p->generator); - if (p->generator_early) (void) rmdir(p->generator_early); - if (p->generator_late) (void) rmdir(p->generator_late); } diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index ad05c0c537..f9bb2fe237 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -26,6 +26,10 @@ typedef struct LookupPaths LookupPaths; #include "install.h" #include "macro.h" +typedef enum LookupPathsFlags { + LOOKUP_PATHS_EXCLUDE_GENERATED = 1, +} LookupPathsFlags; + struct LookupPaths { /* Where we look for unit files. This includes the individual special paths below, but also any vendor * supplied, static unit file paths. */ @@ -58,7 +62,7 @@ struct LookupPaths { char *root_dir; }; -int lookup_paths_init(LookupPaths *p, UnitFileScope scope, const char *root_dir); +int lookup_paths_init(LookupPaths *p, UnitFileScope scope, LookupPathsFlags flags, const char *root_dir); int lookup_paths_reduce(LookupPaths *p); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 7c259ba06f..3344d25f77 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -4810,7 +4810,7 @@ static int cat(int argc, char *argv[], void *userdata) { return -EINVAL; } - r = lookup_paths_init(&lp, arg_scope, arg_root); + r = lookup_paths_init(&lp, arg_scope, 0, arg_root); if (r < 0) return log_error_errno(r, "Failed to determine unit paths: %m"); @@ -5240,7 +5240,7 @@ static int enable_sysv_units(const char *verb, char **args) { "is-enabled")) return 0; - r = lookup_paths_init(&paths, arg_scope, arg_root); + r = lookup_paths_init(&paths, arg_scope, LOOKUP_PATHS_EXCLUDE_GENERATED, arg_root); if (r < 0) return r; @@ -6073,7 +6073,7 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { assert(names); assert(paths); - r = lookup_paths_init(&lp, arg_scope, arg_root); + r = lookup_paths_init(&lp, arg_scope, 0, arg_root); if (r < 0) return r; diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c index fb7c47e1c8..e44304c16a 100644 --- a/src/sysv-generator/sysv-generator.c +++ b/src/sysv-generator/sysv-generator.c @@ -1004,7 +1004,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = lookup_paths_init(&lp, UNIT_FILE_SYSTEM, NULL); + r = lookup_paths_init(&lp, UNIT_FILE_SYSTEM, LOOKUP_PATHS_EXCLUDE_GENERATED, NULL); if (r < 0) { log_error_errno(r, "Failed to find lookup paths: %m"); goto finish; diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c index ba60482867..096326d176 100644 --- a/src/test/test-path-lookup.c +++ b/src/test/test-path-lookup.c @@ -36,13 +36,13 @@ static void test_paths(UnitFileScope scope) { assert_se(mkdtemp(template)); assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0); - assert_se(lookup_paths_init(&lp_without_env, scope, NULL) >= 0); + assert_se(lookup_paths_init(&lp_without_env, scope, 0, NULL) >= 0); assert_se(!strv_isempty(lp_without_env.search_path)); assert_se(lookup_paths_reduce(&lp_without_env) >= 0); systemd_unit_path = strjoina(template, "/systemd-unit-path"); assert_se(setenv("SYSTEMD_UNIT_PATH", systemd_unit_path, 1) == 0); - assert_se(lookup_paths_init(&lp_with_env, scope, NULL) == 0); + assert_se(lookup_paths_init(&lp_with_env, scope, 0, NULL) == 0); assert_se(strv_length(lp_with_env.search_path) == 1); assert_se(streq(lp_with_env.search_path[0], systemd_unit_path)); assert_se(lookup_paths_reduce(&lp_with_env) >= 0); -- cgit v1.2.3-54-g00ecf From 6eb7c172b58d81a5f6c3998ce304a7324fc65050 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Apr 2016 11:27:28 +0200 Subject: tree-wide: add new SIGNAL_VALID() macro-like function that validates signal numbers And port all code over to use it. --- src/basic/signal-util.c | 2 +- src/basic/signal-util.h | 4 ++++ src/core/dbus-kill.c | 4 ++-- src/core/dbus-unit.c | 5 +++-- src/core/unit.c | 4 ++-- src/libsystemd/sd-event/sd-event.c | 5 ++--- src/login/logind-session-dbus.c | 3 ++- src/login/logind-user-dbus.c | 3 ++- src/machine/machine-dbus.c | 3 ++- 9 files changed, 20 insertions(+), 13 deletions(-) (limited to 'src/core') diff --git a/src/basic/signal-util.c b/src/basic/signal-util.c index e3047b209b..280b5c3251 100644 --- a/src/basic/signal-util.c +++ b/src/basic/signal-util.c @@ -255,7 +255,7 @@ int signal_from_string(const char *s) { } if (safe_atou(s, &u) >= 0) { signo = (int) u + offset; - if (signo > 0 && signo < _NSIG) + if (SIGNAL_VALID(signo)) return signo; } return -EINVAL; diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h index a7322ff26a..dfd6eb564d 100644 --- a/src/basic/signal-util.h +++ b/src/basic/signal-util.h @@ -50,3 +50,7 @@ static inline void block_signals_reset(sigset_t *ss) { assert_se(sigprocmask_many(SIG_BLOCK, &t, __VA_ARGS__, -1) >= 0); \ t; \ }) + +static inline bool SIGNAL_VALID(int signo) { + return signo > 0 && signo < _NSIG; +} diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c index fc50fafaad..0f54c6b84b 100644 --- a/src/core/dbus-kill.c +++ b/src/core/dbus-kill.c @@ -58,7 +58,7 @@ int bus_kill_context_set_transient_property( k = kill_mode_from_string(m); if (k < 0) - return -EINVAL; + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Kill mode '%s' not known.", m); if (mode != UNIT_CHECK) { c->kill_mode = k; @@ -75,7 +75,7 @@ int bus_kill_context_set_transient_property( if (r < 0) return r; - if (sig <= 0 || sig >= _NSIG) + if (!SIGNAL_VALID(sig)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal %i out of range", sig); if (mode != UNIT_CHECK) { diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index b351f6a2c2..c507265070 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -27,6 +27,7 @@ #include "locale-util.h" #include "log.h" #include "selinux-access.h" +#include "signal-util.h" #include "special.h" #include "string-util.h" #include "strv.h" @@ -547,7 +548,7 @@ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error * return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho); } - if (signo <= 0 || signo >= _NSIG) + if (!SIGNAL_VALID(signo)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range."); r = bus_verify_manage_units_async_full( @@ -1002,7 +1003,6 @@ int bus_unit_queue_job( type = JOB_TRY_RELOAD; } - if (type == JOB_STOP && (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) && unit_active_state(u) == UNIT_INACTIVE) @@ -1259,6 +1259,7 @@ int bus_unit_set_properties( } int bus_unit_check_load_state(Unit *u, sd_bus_error *error) { + assert(u); if (u->load_state == UNIT_LOADED) return 0; diff --git a/src/core/unit.c b/src/core/unit.c index c028f57f13..a8174e6041 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -47,6 +47,7 @@ #include "path-util.h" #include "process-util.h" #include "set.h" +#include "signal-util.h" #include "special.h" #include "stat-util.h" #include "stdio-util.h" @@ -3062,8 +3063,7 @@ bool unit_active_or_pending(Unit *u) { int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) { assert(u); assert(w >= 0 && w < _KILL_WHO_MAX); - assert(signo > 0); - assert(signo < _NSIG); + assert(SIGNAL_VALID(signo)); if (!UNIT_VTABLE(u)->kill) return -EOPNOTSUPP; diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 841358ed03..9fd744768d 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -1145,8 +1145,7 @@ _public_ int sd_event_add_signal( int r; assert_return(e, -EINVAL); - assert_return(sig > 0, -EINVAL); - assert_return(sig < _NSIG, -EINVAL); + assert_return(SIGNAL_VALID(sig), -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); @@ -2200,7 +2199,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { if (_unlikely_(n != sizeof(si))) return -EIO; - assert(si.ssi_signo < _NSIG); + assert(SIGNAL_VALID(si.ssi_signo)); read_one = true; diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index ff9170683b..0f8862c0d9 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -28,6 +28,7 @@ #include "logind-session-device.h" #include "logind-session.h" #include "logind.h" +#include "signal-util.h" #include "strv.h" #include "util.h" @@ -300,7 +301,7 @@ int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho); } - if (signo <= 0 || signo >= _NSIG) + if (!SIGNAL_VALID(signo)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo); r = bus_verify_polkit_async( diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c index fd98c7beca..b73f9ea69e 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -25,6 +25,7 @@ #include "formats-util.h" #include "logind-user.h" #include "logind.h" +#include "signal-util.h" #include "strv.h" #include "user-util.h" @@ -222,7 +223,7 @@ int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error * if (r < 0) return r; - if (signo <= 0 || signo >= _NSIG) + if (!SIGNAL_VALID(signo)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo); r = user_kill(u, signo); diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index c5bbf2fbde..c7ff0efac8 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -46,6 +46,7 @@ #include "mkdir.h" #include "path-util.h" #include "process-util.h" +#include "signal-util.h" #include "strv.h" #include "terminal-util.h" #include "user-util.h" @@ -166,7 +167,7 @@ int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho); } - if (signo <= 0 || signo >= _NSIG) + if (!SIGNAL_VALID(signo)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo); r = bus_verify_polkit_async( -- cgit v1.2.3-54-g00ecf From 344ca7556bf6c1c8727c19a0eb8751a27dc0a85f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Apr 2016 18:00:36 +0200 Subject: core,systemctl: add new "systemctl revert" command This allows dropping all user configuration and reverting back to the vendor default of a unit file. It basically undoes what "systemctl edit", "systemctl set-property" and "systemctl mask" do. --- man/systemctl.xml | 22 ++++ src/core/dbus-manager.c | 28 ++++ src/core/org.freedesktop.systemd1.conf | 4 + src/shared/install.c | 234 +++++++++++++++++++++++++++++++-- src/shared/install.h | 3 +- src/systemctl/systemctl.c | 20 ++- src/test/test-install-root.c | 52 ++++++++ 7 files changed, 347 insertions(+), 16 deletions(-) (limited to 'src/core') diff --git a/man/systemctl.xml b/man/systemctl.xml index 064777810f..5f624243f7 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1244,6 +1244,28 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service + + revert NAME... + + + Revert one or more unit files to their vendor versions. This command removes drop-in configuration + files that modify the specified units, as well as any user-configured unit file that overrides a matching + vendor supplied unit file. Specifically, for a unit foo.service the matching directories + foo.service.d/ with all their contained files are removed, both below the persistent and + runtime configuration directories (i.e. below /etc/systemd/system and + /run/systemd/system); if the unit file has a vendor-supplied version (i.e. a unit file + located below /usr) any matching peristent or runtime unit file that overrides it is + removed, too. Note that if a unit file has no vendor-supplied version (i.e. is only defined below + /etc/systemd/system or /run/systemd/system, but not in a unit + file stored below /usr), then it is not removed. Also, if a unit is masked, it is + unmasked. + + Effectively, this command may be used to undo all changes made with systemctl + edit, systemctl set-property and systemctl mask and puts + the original unit file with its settings back in effect. + + + add-wants TARGET NAME... diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index f0ee2fcb36..41f27ec26b 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1758,6 +1758,33 @@ static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_ return method_disable_unit_files_generic(message, userdata, "enable", unit_file_unmask, error); } +static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + UnitFileChange *changes = NULL; + unsigned n_changes = 0; + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + r = bus_verify_manage_unit_files_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = unit_file_revert(m->unit_file_scope, NULL, l, &changes, &n_changes); + if (r < 0) + return r; + + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); +} + static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) { UnitFileChange *changes = NULL; unsigned n_changes = 0; @@ -2005,6 +2032,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RevertUnitFiles", "as", "a(sss)", method_revert_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 6a7a37ee92..f78eedbd6e 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -174,6 +174,10 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="LinkUnitFiles"/> + + diff --git a/src/shared/install.c b/src/shared/install.c index 8fc9205107..8d9f96553b 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -45,6 +45,7 @@ #include "mkdir.h" #include "path-lookup.h" #include "path-util.h" +#include "rm-rf.h" #include "set.h" #include "special.h" #include "stat-util.h" @@ -136,27 +137,35 @@ static int path_is_transient(const LookupPaths *p, const char *path) { return path_equal(p->transient, parent); } -static int path_is_config(const LookupPaths *p, const char *path) { +static int path_is_control(const LookupPaths *p, const char *path) { _cleanup_free_ char *parent = NULL; - const char *rpath; assert(p); assert(path); - /* Checks whether the specified path is intended for configuration or is outside of it. We check both the - * top-level directory and the one actually configured. The latter is particularly relevant for cases where we - * operate on a root directory. */ + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; - rpath = skip_root(p, path); - if (rpath && (path_startswith(rpath, "/etc") || path_startswith(rpath, "/run"))) - return true; + return path_equal(parent, p->persistent_control) || + path_equal(parent, p->runtime_control); +} + +static int path_is_config(const LookupPaths *p, const char *path) { + _cleanup_free_ char *parent = NULL; + + assert(p); + assert(path); + + /* Note that we do *not* have generic checks for /etc or /run in place, since with them we couldn't discern + * configuration from transient or generated units */ parent = dirname_malloc(path); if (!parent) return -ENOMEM; return path_equal(parent, p->persistent_config) || - path_equal(parent, p->runtime_config); + path_equal(parent, p->runtime_config); } static int path_is_runtime(const LookupPaths *p, const char *path) { @@ -166,6 +175,9 @@ static int path_is_runtime(const LookupPaths *p, const char *path) { assert(p); assert(path); + /* Everything in /run is considered runtime. On top of that we also add explicit checks for the various runtime + * directories, as safety net. */ + rpath = skip_root(p, path); if (rpath && path_startswith(rpath, "/run")) return true; @@ -174,7 +186,33 @@ static int path_is_runtime(const LookupPaths *p, const char *path) { if (!parent) return -ENOMEM; - return path_equal(parent, p->runtime_config); + return path_equal(parent, p->runtime_config) || + path_equal(parent, p->generator) || + path_equal(parent, p->generator_early) || + path_equal(parent, p->generator_late) || + path_equal(parent, p->transient) || + path_equal(parent, p->runtime_control); +} + +static int path_is_vendor(const LookupPaths *p, const char *path) { + const char *rpath; + + assert(p); + assert(path); + + rpath = skip_root(p, path); + if (!rpath) + return 0; + + if (path_startswith(rpath, "/usr")) + return true; + +#ifdef HAVE_SPLIT_USR + if (path_startswith(rpath, "/lib")) + return true; +#endif + + return path_equal(rpath, SYSTEM_DATA_UNIT_PATH); } int unit_file_changes_add( @@ -1703,6 +1741,182 @@ int unit_file_link( return r; } +static int path_shall_revert(const LookupPaths *paths, const char *path) { + int r; + + assert(paths); + assert(path); + + /* Checks whether the path is one where the drop-in directories shall be removed. */ + + r = path_is_config(paths, path); + if (r != 0) + return r; + + r = path_is_control(paths, path); + if (r != 0) + return r; + + return path_is_transient(paths, path); +} + +int unit_file_revert( + UnitFileScope scope, + const char *root_dir, + char **files, + UnitFileChange **changes, + unsigned *n_changes) { + + _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; + /* _cleanup_(install_context_done) InstallContext c = {}; */ + _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_strv_free_ char **todo = NULL; + size_t n_todo = 0, n_allocated = 0; + char **i; + int r, q; + + /* Puts a unit file back into vendor state. This means: + * + * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and + * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated"). + * + * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in + * "config", but not in "transient" or "control" or even "generated"). + * + * We remove all that in both the runtime and the persistant directories, if that applies. + */ + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + STRV_FOREACH(i, files) { + bool has_vendor = false; + char **p; + + if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) + return -EINVAL; + + STRV_FOREACH(p, paths.search_path) { + _cleanup_free_ char *path = NULL, *dropin = NULL; + struct stat st; + + path = path_make_absolute(*i, *p); + if (!path) + return -ENOMEM; + + r = lstat(path, &st); + if (r < 0) { + if (errno != ENOENT) + return -errno; + } else if (S_ISREG(st.st_mode)) { + /* Check if there's a vendor version */ + r = path_is_vendor(&paths, path); + if (r < 0) + return r; + if (r > 0) + has_vendor = true; + } + + dropin = strappend(path, ".d"); + if (!dropin) + return -ENOMEM; + + r = lstat(dropin, &st); + if (r < 0) { + if (errno != ENOENT) + return -errno; + } else if (S_ISDIR(st.st_mode)) { + /* Remove the drop-ins */ + r = path_shall_revert(&paths, dropin); + if (r < 0) + return r; + if (r > 0) { + if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) + return -ENOMEM; + + todo[n_todo++] = dropin; + dropin = NULL; + } + } + } + + if (!has_vendor) + continue; + + /* OK, there's a vendor version, hence drop all configuration versions */ + STRV_FOREACH(p, paths.search_path) { + _cleanup_free_ char *path = NULL; + struct stat st; + + path = path_make_absolute(*i, *p); + if (!path) + return -ENOMEM; + + r = lstat(path, &st); + if (r < 0) { + if (errno != ENOENT) + return -errno; + } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { + r = path_is_config(&paths, path); + if (r < 0) + return r; + if (r > 0) { + if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) + return -ENOMEM; + + todo[n_todo++] = path; + path = NULL; + } + } + } + } + + strv_uniq(todo); + + r = 0; + STRV_FOREACH(i, todo) { + _cleanup_strv_free_ char **fs = NULL; + const char *rp; + char **j; + + (void) get_files_in_directory(*i, &fs); + + q = rm_rf(*i, REMOVE_ROOT|REMOVE_PHYSICAL); + if (q < 0 && q != -ENOENT && r >= 0) { + r = q; + continue; + } + + STRV_FOREACH(j, fs) { + _cleanup_free_ char *t = NULL; + + t = strjoin(*i, "/", *j, NULL); + if (!t) + return -ENOMEM; + + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, t, NULL); + } + + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, *i, NULL); + + rp = skip_root(&paths, *i); + q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: *i); + if (q < 0) + return q; + } + + q = remove_marked_symlinks(remove_symlinks_to, paths.runtime_config, &paths, changes, n_changes); + if (r >= 0) + r = q; + + q = remove_marked_symlinks(remove_symlinks_to, paths.persistent_config, &paths, changes, n_changes); + if (r >= 0) + r = q; + + return r; +} + int unit_file_add_dependency( UnitFileScope scope, bool runtime, diff --git a/src/shared/install.h b/src/shared/install.h index 8d54fd14ad..6f8b45d4f6 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -128,11 +128,12 @@ static inline bool UNIT_FILE_INSTALL_INFO_HAS_ALSO(UnitFileInstallInfo *i) { int unit_file_enable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_disable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes); int unit_file_reenable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); -int unit_file_link(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_preset(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFilePresetMode mode, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_preset_all(UnitFileScope scope, bool runtime, const char *root_dir, UnitFilePresetMode mode, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes); +int unit_file_link(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); +int unit_file_revert(UnitFileScope scope, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes); int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name); int unit_file_add_dependency(UnitFileScope scope, bool runtime, const char *root_dir, char **files, const char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 3344d25f77..b94af9cf08 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -1993,7 +1993,7 @@ static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_cha if (changes[i].type == UNIT_FILE_SYMLINK) log_info("Created symlink %s, pointing to %s.", changes[i].path, changes[i].source); else - log_info("Removed symlink %s.", changes[i].path); + log_info("Removed %s.", changes[i].path); } } @@ -5437,6 +5437,8 @@ static int enable_unit(int argc, char *argv[], void *userdata) { r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); else if (streq(verb, "unmask")) r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes); + else if (streq(verb, "revert")) + r = unit_file_revert(arg_scope, arg_root, names, &changes, &n_changes); else assert_not_reached("Unknown verb"); @@ -5455,7 +5457,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) { _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; int expect_carries_install_info = false; - bool send_force = true, send_preset_mode = false; + bool send_runtime = true, send_force = true, send_preset_mode = false; const char *method; sd_bus *bus; @@ -5490,6 +5492,9 @@ static int enable_unit(int argc, char *argv[], void *userdata) { else if (streq(verb, "unmask")) { method = "UnmaskUnitFiles"; send_force = false; + } else if (streq(verb, "revert")) { + method = "RevertUnitFiles"; + send_runtime = send_force = false; } else assert_not_reached("Unknown verb"); @@ -5513,9 +5518,11 @@ static int enable_unit(int argc, char *argv[], void *userdata) { return bus_log_create_error(r); } - r = sd_bus_message_append(m, "b", arg_runtime); - if (r < 0) - return bus_log_create_error(r); + if (send_runtime) { + r = sd_bus_message_append(m, "b", arg_runtime); + if (r < 0) + return bus_log_create_error(r); + } if (send_force) { r = sd_bus_message_append(m, "b", arg_force); @@ -6280,6 +6287,8 @@ static void systemctl_help(void) { " unmask NAME... Unmask one or more units\n" " link PATH... Link one or more units files into\n" " the search path\n" + " revert NAME... Revert one or more unit files to vendor\n" + " version\n" " add-wants TARGET NAME... Add 'Wants' dependency for the target\n" " on specified one or more units\n" " add-requires TARGET NAME... Add 'Requires' dependency for the target\n" @@ -7403,6 +7412,7 @@ static int systemctl_main(int argc, char *argv[]) { { "mask", 2, VERB_ANY, 0, enable_unit }, { "unmask", 2, VERB_ANY, 0, enable_unit }, { "link", 2, VERB_ANY, 0, enable_unit }, + { "revert", 2, VERB_ANY, 0, enable_unit }, { "switch-root", 2, VERB_ANY, VERB_NOCHROOT, switch_root }, { "list-dependencies", VERB_ANY, 2, VERB_NOCHROOT, list_dependencies }, { "set-default", 2, 2, 0, set_default }, diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c index bc4206a1b0..2138655e29 100644 --- a/src/test/test-install-root.c +++ b/src/test/test-install-root.c @@ -630,6 +630,57 @@ static void test_preset_and_list(const char *root) { assert_se(got_yes && got_no); } +static void test_revert(const char *root) { + const char *p; + UnitFileState state; + UnitFileChange *changes = NULL; + unsigned n_changes = 0; + + assert(root); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "yy.service", NULL) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/xx.service"); + assert_se(write_string_file(p, "# Empty\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) >= 0); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", &state) >= 0 && state == UNIT_FILE_STATIC); + + /* Initially there's nothing to revert */ + assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 0); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service"); + assert_se(write_string_file(p, "# Empty override\n", WRITE_STRING_FILE_CREATE) >= 0); + + /* Revert the override file */ + assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d/dropin.conf"); + assert_se(mkdir_parents(p, 0755) >= 0); + assert_se(write_string_file(p, "# Empty dropin\n", WRITE_STRING_FILE_CREATE) >= 0); + + /* Revert the dropin file */ + assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 2); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + assert_se(streq(changes[0].path, p)); + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d"); + assert_se(changes[1].type == UNIT_FILE_UNLINK); + assert_se(streq(changes[1].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; +} + int main(int argc, char *argv[]) { char root[] = "/tmp/rootXXXXXX"; const char *p; @@ -658,6 +709,7 @@ int main(int argc, char *argv[]) { test_template_enable(root); test_indirect(root); test_preset_and_list(root); + test_revert(root); assert_se(rm_rf(root, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); -- cgit v1.2.3-54-g00ecf From e20b2a867ac5ac7ff6d43898fb83bc78f730909e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Apr 2016 18:10:32 +0200 Subject: core: when creating a drop-in snippet, add a comment explaining this to it --- src/core/unit.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/unit.c b/src/core/unit.c index a8174e6041..fb4f3ddff6 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3357,7 +3357,7 @@ static const char* unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode) { int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) { _cleanup_free_ char *p = NULL, *q = NULL; - const char *dir; + const char *dir, *prefixed; int r; assert(u); @@ -3376,7 +3376,10 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co if (!dir) return -EINVAL; - r = write_drop_in(dir, u->id, 50, name, data); + prefixed = strjoina("# This is a drop-in unit file extension, created via \"systemctl set-property\" or an equivalent operation. Do not edit.\n", + data); + + r = write_drop_in(dir, u->id, 50, name, prefixed); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 815b09d39b74a9ece31b7d7ef45f8f00784b8d8b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Apr 2016 18:13:02 +0200 Subject: core: optimize unit_write_drop_in a bit There's no point in first determining the drop-in file name path, then forgetting it again, and then determining it again. Instead, just generated it once, and then write to ti directly. --- src/core/unit.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/unit.c b/src/core/unit.c index fb4f3ddff6..08f3288776 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3379,17 +3379,19 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co prefixed = strjoina("# This is a drop-in unit file extension, created via \"systemctl set-property\" or an equivalent operation. Do not edit.\n", data); - r = write_drop_in(dir, u->id, 50, name, prefixed); + r = drop_in_file(dir, u->id, 50, name, &p, &q); if (r < 0) return r; - r = drop_in_file(dir, u->id, 50, name, &p, &q); + (void) mkdir_p(p, 0755); + r = write_string_file_atomic_label(q, prefixed); if (r < 0) return r; - r = strv_extend(&u->dropin_paths, q); + r = strv_push(&u->dropin_paths, q); if (r < 0) return r; + q = NULL; strv_uniq(u->dropin_paths); -- cgit v1.2.3-54-g00ecf From 8e20adcaa0cf06a85d36e2fda35fa1d70d5d63c8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 11 Apr 2016 17:57:05 +0200 Subject: core: make sure we generate a nicer error when a linked unit is attempted to be enabled We don't allow using config symlinks to enable units, but the error message we printed was awful. Fix that, and generate a more readable error. Fixes #3010. --- src/core/dbus-manager.c | 35 ++++++++++++++++++------------- src/libsystemd/sd-bus/bus-common-errors.c | 1 + src/libsystemd/sd-bus/bus-common-errors.h | 1 + src/systemctl/systemctl.c | 2 ++ 4 files changed, 24 insertions(+), 15 deletions(-) (limited to 'src/core') diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 41f27ec26b..0939a55182 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1607,6 +1607,19 @@ fail: return r; } +static int install_error(sd_bus_error *error, int c) { + assert(c < 0); + + if (c == -ESHUTDOWN) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked."); + if (c == -EADDRNOTAVAIL) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, "Unit file is transient or generated."); + if (c == -ELOOP) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_LINKED, "Refusing to operate on linked unit file."); + + return c; +} + static int method_enable_unit_files_generic( sd_bus_message *message, Manager *m, @@ -1638,12 +1651,8 @@ static int method_enable_unit_files_generic( return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = call(m->unit_file_scope, runtime, NULL, l, force, &changes, &n_changes); - if (r == -ESHUTDOWN) - return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked."); - if (r == -EADDRNOTAVAIL) - return sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, "Unit file is transient or generated."); if (r < 0) - return r; + return install_error(error, r); return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes); } @@ -1709,7 +1718,7 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use r = unit_file_preset(m->unit_file_scope, runtime, NULL, l, mm, force, &changes, &n_changes); if (r < 0) - return r; + return install_error(error, r); return reply_unit_file_changes_and_free(m, message, r, changes, n_changes); } @@ -1745,7 +1754,7 @@ static int method_disable_unit_files_generic( r = call(m->unit_file_scope, runtime, NULL, l, &changes, &n_changes); if (r < 0) - return r; + return install_error(error, r); return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } @@ -1780,7 +1789,7 @@ static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_ r = unit_file_revert(m->unit_file_scope, NULL, l, &changes, &n_changes); if (r < 0) - return r; + return install_error(error, r); return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } @@ -1811,7 +1820,7 @@ static int method_set_default_target(sd_bus_message *message, void *userdata, sd r = unit_file_set_default(m->unit_file_scope, NULL, name, force, &changes, &n_changes); if (r < 0) - return r; + return install_error(error, r); return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } @@ -1852,7 +1861,7 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, r = unit_file_preset_all(m->unit_file_scope, runtime, NULL, mm, force, &changes, &n_changes); if (r < 0) { unit_file_changes_free(changes, n_changes); - return r; + return install_error(error, r); } return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); @@ -1890,12 +1899,8 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd return -EINVAL; r = unit_file_add_dependency(m->unit_file_scope, runtime, NULL, l, target, dep, force, &changes, &n_changes); - if (r == -ESHUTDOWN) - return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked."); - if (r == -EADDRNOTAVAIL) - return sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, "Unit file is transient or generated."); if (r < 0) - return r; + return install_error(error, r); return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index f16878cd1a..02e3bf904c 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -39,6 +39,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, EDEADLK), SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED, ESHUTDOWN), SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_GENERATED, EADDRNOTAVAIL), + SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_LINKED, ELOOP), SD_BUS_ERROR_MAP(BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, EBADR), SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION, EPERM), SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index c16605ba87..c8f369cb78 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -35,6 +35,7 @@ #define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive" #define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked" #define BUS_ERROR_UNIT_GENERATED "org.freedesktop.systemd1.UnitGenerated" +#define BUS_ERROR_UNIT_LINKED "org.freedesktop.systemd1.UnitLinked" #define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable" #define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation" #define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown" diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index b94af9cf08..9efdc63dde 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5446,6 +5446,8 @@ static int enable_unit(int argc, char *argv[], void *userdata) { return log_error_errno(r, "Unit file is masked."); if (r == -EADDRNOTAVAIL) return log_error_errno(r, "Unit file is transient or generated."); + if (r == -ELOOP) + return log_error_errno(r, "Refusing to operate on linked unit file."); if (r < 0) return log_error_errno(r, "Operation failed: %m"); -- cgit v1.2.3-54-g00ecf From f9ba08fb4fcd64aaf6896d8a5b586180f244fcb7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 11 Apr 2016 18:20:02 +0200 Subject: core: keep track of the mtime of the transient unit file we wrote Otherwise "systemctl status" will immediately report that our unit file is out of date. --- src/core/unit.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core') diff --git a/src/core/unit.c b/src/core/unit.c index 08f3288776..fb88260d23 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1243,6 +1243,8 @@ int unit_load(Unit *u) { fclose(u->transient_file); u->transient_file = NULL; + + u->dropin_mtime = now(CLOCK_REALTIME); } if (UNIT_VTABLE(u)->load) { -- cgit v1.2.3-54-g00ecf From 99ef0330e15db969f7b096cedeecf63a09efbe86 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 12 Apr 2016 13:51:06 +0200 Subject: core: make sure we always free the list of changes --- src/core/dbus-manager.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 0939a55182..2392ed6c16 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1651,8 +1651,10 @@ static int method_enable_unit_files_generic( return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = call(m->unit_file_scope, runtime, NULL, l, force, &changes, &n_changes); - if (r < 0) + if (r < 0) { + unit_file_changes_free(changes, n_changes); return install_error(error, r); + } return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes); } @@ -1717,8 +1719,10 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = unit_file_preset(m->unit_file_scope, runtime, NULL, l, mm, force, &changes, &n_changes); - if (r < 0) + if (r < 0) { + unit_file_changes_free(changes, n_changes); return install_error(error, r); + } return reply_unit_file_changes_and_free(m, message, r, changes, n_changes); } @@ -1753,8 +1757,10 @@ static int method_disable_unit_files_generic( return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = call(m->unit_file_scope, runtime, NULL, l, &changes, &n_changes); - if (r < 0) + if (r < 0) { + unit_file_changes_free(changes, n_changes); return install_error(error, r); + } return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } @@ -1788,8 +1794,10 @@ static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = unit_file_revert(m->unit_file_scope, NULL, l, &changes, &n_changes); - if (r < 0) + if (r < 0) { + unit_file_changes_free(changes, n_changes); return install_error(error, r); + } return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } @@ -1819,8 +1827,10 @@ static int method_set_default_target(sd_bus_message *message, void *userdata, sd return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = unit_file_set_default(m->unit_file_scope, NULL, name, force, &changes, &n_changes); - if (r < 0) + if (r < 0) { + unit_file_changes_free(changes, n_changes); return install_error(error, r); + } return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } @@ -1899,8 +1909,10 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd return -EINVAL; r = unit_file_add_dependency(m->unit_file_scope, runtime, NULL, l, target, dep, force, &changes, &n_changes); - if (r < 0) + if (r < 0) { + unit_file_changes_free(changes, n_changes); return install_error(error, r); + } return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } -- cgit v1.2.3-54-g00ecf