diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 68a108742a..758dd8f1b8 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -2272,7 +2272,7 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use UnitFileChange *changes = NULL; size_t n_changes = 0; Manager *m = userdata; - UnitFilePresetMode mm; + UnitFilePresetMode preset_mode; int runtime, force, r; UnitFileFlags flags; const char *mode; @@ -2291,10 +2291,10 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use flags = unit_file_bools_to_flags(runtime, force); if (isempty(mode)) - mm = UNIT_FILE_PRESET_FULL; + preset_mode = UNIT_FILE_PRESET_FULL; else { - mm = unit_file_preset_mode_from_string(mode); - if (mm < 0) + preset_mode = unit_file_preset_mode_from_string(mode); + if (preset_mode < 0) return -EINVAL; } @@ -2304,7 +2304,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 */ - r = unit_file_preset(m->unit_file_scope, flags, NULL, l, mm, &changes, &n_changes); + r = unit_file_preset(m->unit_file_scope, flags, NULL, l, preset_mode, &changes, &n_changes); if (r < 0) return install_error(error, r, changes, n_changes); @@ -2436,7 +2436,7 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, UnitFileChange *changes = NULL; size_t n_changes = 0; Manager *m = userdata; - UnitFilePresetMode mm; + UnitFilePresetMode preset_mode; const char *mode; UnitFileFlags flags; int force, runtime, r; @@ -2455,10 +2455,10 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, flags = unit_file_bools_to_flags(runtime, force); if (isempty(mode)) - mm = UNIT_FILE_PRESET_FULL; + preset_mode = UNIT_FILE_PRESET_FULL; else { - mm = unit_file_preset_mode_from_string(mode); - if (mm < 0) + preset_mode = unit_file_preset_mode_from_string(mode); + if (preset_mode < 0) return -EINVAL; } @@ -2468,7 +2468,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 */ - r = unit_file_preset_all(m->unit_file_scope, flags, NULL, mm, &changes, &n_changes); + r = unit_file_preset_all(m->unit_file_scope, flags, NULL, preset_mode, &changes, &n_changes); if (r < 0) return install_error(error, r, changes, n_changes); diff --git a/src/shared/install.c b/src/shared/install.c index b6dc0c6e60..ba4fa5b136 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -269,7 +269,6 @@ int unit_file_changes_add( _cleanup_free_ char *p = NULL, *s = NULL; UnitFileChange *c; - assert(path); assert(!changes == !n_changes); if (type_or_errno >= 0) @@ -285,11 +284,13 @@ int unit_file_changes_add( return -ENOMEM; *changes = c; - p = strdup(path); - if (!p) - return -ENOMEM; + if (path) { + p = strdup(path); + if (!p) + return -ENOMEM; - path_simplify(p); + path_simplify(p); + } if (source) { s = strdup(source); @@ -355,6 +356,10 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang log_warning("Unit %s is added as a dependency to a non-existent unit %s.", changes[i].source, changes[i].path); break; + case UNIT_FILE_AUXILIARY_FAILED: + if (!quiet) + log_warning("Failed to enable auxiliary unit %s, ignoring.", changes[i].source); + break; case -EEXIST: if (changes[i].source) log_error_errno(changes[i].type_or_errno, @@ -377,8 +382,8 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang logged = true; break; case -EIDRM: - log_error_errno(changes[i].type_or_errno, "Failed to %s unit, unit %s is a non-template unit.", - verb, changes[i].path); + log_error_errno(changes[i].type_or_errno, "Failed to %s %s, destination unit %s is a non-template unit.", + verb, changes[i].source, changes[i].path); logged = true; break; case -EUCLEAN: @@ -1843,6 +1848,7 @@ static int install_info_symlink_alias( static int install_info_symlink_wants( UnitFileScope scope, + UnitFileFlags file_flags, UnitFileInstallInfo *i, const LookupPaths *paths, const char *config_path, @@ -1910,8 +1916,16 @@ static int install_info_symlink_wants( return q; if (!unit_name_is_valid(dst, valid_dst_type)) { - /* Generate a proper error here: EUCLEAN if the name is generally bad, - * EIDRM if the template status doesn't match. */ + /* Generate a proper error here: EUCLEAN if the name is generally bad, EIDRM if the + * template status doesn't match. If we are doing presets don't bother reporting the + * error. This also covers cases like 'systemctl preset serial-getty@.service', which + * has no DefaultInstance, so there is nothing we can do. At the same time, + * 'systemctl enable serial-getty@.service' should fail, the user should specify an + * instance like in 'systemctl enable serial-getty@ttyS0.service'. + */ + if (file_flags & UNIT_FILE_IGNORE_AUXILIARY_FAILURE) + continue; + if (unit_name_is_valid(dst, UNIT_NAME_ANY)) { unit_file_changes_add(changes, n_changes, -EIDRM, dst, n); r = -EIDRM; @@ -1969,10 +1983,10 @@ static int install_info_symlink_link( static int install_info_apply( UnitFileScope scope, + UnitFileFlags file_flags, UnitFileInstallInfo *i, const LookupPaths *paths, const char *config_path, - bool force, UnitFileChange **changes, size_t *n_changes) { @@ -1985,13 +1999,15 @@ static int install_info_apply( if (i->type != UNIT_FILE_TYPE_REGULAR) return 0; + bool force = file_flags & UNIT_FILE_FORCE; + r = install_info_symlink_alias(i, paths, config_path, force, changes, n_changes); - q = install_info_symlink_wants(scope, i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes); + q = install_info_symlink_wants(scope, file_flags, i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes); if (r == 0) r = q; - q = install_info_symlink_wants(scope, i, paths, config_path, i->required_by, ".requires/", changes, n_changes); + q = install_info_symlink_wants(scope, file_flags, i, paths, config_path, i->required_by, ".requires/", changes, n_changes); if (r == 0) r = q; @@ -2005,10 +2021,10 @@ static int install_info_apply( static int install_context_apply( UnitFileScope scope, + UnitFileFlags file_flags, InstallContext *c, const LookupPaths *paths, const char *config_path, - bool force, SearchFlags flags, UnitFileChange **changes, size_t *n_changes) { @@ -2037,6 +2053,13 @@ static int install_context_apply( q = install_info_traverse(scope, c, paths, i, flags, NULL); if (q < 0) { + if (i->auxiliary) { + q = unit_file_changes_add(changes, n_changes, UNIT_FILE_AUXILIARY_FAILED, NULL, i->name); + if (q < 0) + return q; + continue; + } + unit_file_changes_add(changes, n_changes, q, i->name, NULL); return q; } @@ -2055,7 +2078,7 @@ static int install_context_apply( if (i->type != UNIT_FILE_TYPE_REGULAR) continue; - q = install_info_apply(scope, i, paths, config_path, force, changes, n_changes); + q = install_info_apply(scope, file_flags, i, paths, config_path, changes, n_changes); if (r >= 0) { if (q < 0) r = q; @@ -2528,7 +2551,7 @@ int unit_file_revert( int unit_file_add_dependency( UnitFileScope scope, - UnitFileFlags flags, + UnitFileFlags file_flags, const char *root_dir, char **files, const char *target, @@ -2557,7 +2580,7 @@ int unit_file_add_dependency( if (r < 0) return r; - config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + config_path = (file_flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; if (!config_path) return -ENXIO; @@ -2593,12 +2616,13 @@ int unit_file_add_dependency( return -ENOMEM; } - return install_context_apply(scope, &c, &paths, config_path, !!(flags & UNIT_FILE_FORCE), SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes); + return install_context_apply(scope, file_flags, &c, &paths, config_path, + SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes); } int unit_file_enable( UnitFileScope scope, - UnitFileFlags flags, + UnitFileFlags file_flags, const char *root_dir, char **files, UnitFileChange **changes, @@ -2618,7 +2642,7 @@ int unit_file_enable( if (r < 0) return r; - config_path = config_path_from_flags(&paths, flags); + config_path = config_path_from_flags(&paths, file_flags); if (!config_path) return -ENXIO; @@ -2636,7 +2660,7 @@ int unit_file_enable( is useful to determine whether the passed files had any installation data at all. */ - return install_context_apply(scope, &c, &paths, config_path, !!(flags & UNIT_FILE_FORCE), SEARCH_LOAD, changes, n_changes); + return install_context_apply(scope, file_flags, &c, &paths, config_path, SEARCH_LOAD, changes, n_changes); } int unit_file_disable( @@ -3166,13 +3190,13 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char static int execute_preset( UnitFileScope scope, + UnitFileFlags file_flags, InstallContext *plus, InstallContext *minus, const LookupPaths *paths, const char *config_path, char **files, UnitFilePresetMode mode, - bool force, UnitFileChange **changes, size_t *n_changes) { @@ -3198,7 +3222,9 @@ static int execute_preset( int q; /* Returns number of symlinks that where supposed to be installed. */ - q = install_context_apply(scope, plus, paths, config_path, force, SEARCH_LOAD, changes, n_changes); + q = install_context_apply(scope, + file_flags | UNIT_FILE_IGNORE_AUXILIARY_FAILURE, + plus, paths, config_path, SEARCH_LOAD, changes, n_changes); if (r >= 0) { if (q < 0) r = q; @@ -3266,7 +3292,7 @@ static int preset_prepare_one( int unit_file_preset( UnitFileScope scope, - UnitFileFlags flags, + UnitFileFlags file_flags, const char *root_dir, char **files, UnitFilePresetMode mode, @@ -3288,7 +3314,7 @@ int unit_file_preset( if (r < 0) return r; - config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + config_path = (file_flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; if (!config_path) return -ENXIO; @@ -3302,12 +3328,12 @@ int unit_file_preset( return r; } - return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes); + return execute_preset(scope, file_flags, &plus, &minus, &paths, config_path, files, mode, changes, n_changes); } int unit_file_preset_all( UnitFileScope scope, - UnitFileFlags flags, + UnitFileFlags file_flags, const char *root_dir, UnitFilePresetMode mode, UnitFileChange **changes, @@ -3328,7 +3354,7 @@ int unit_file_preset_all( if (r < 0) return r; - config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + config_path = (file_flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; if (!config_path) return -ENXIO; @@ -3358,22 +3384,16 @@ int unit_file_preset_all( if (!IN_SET(de->d_type, DT_LNK, DT_REG)) continue; - /* we don't pass changes[] in, because we want to handle errors on our own */ - r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, &presets, NULL, 0); - if (r == -ERFKILL) - r = unit_file_changes_add(changes, n_changes, - UNIT_FILE_IS_MASKED, de->d_name, NULL); - else if (r == -ENOLINK) - r = unit_file_changes_add(changes, n_changes, - UNIT_FILE_IS_DANGLING, de->d_name, NULL); - else if (r == -EADDRNOTAVAIL) /* Ignore generated/transient units when applying preset */ - continue; - if (r < 0) + r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, &presets, changes, n_changes); + if (r < 0 && + !IN_SET(r, -EEXIST, -ERFKILL, -EADDRNOTAVAIL, -EIDRM, -EUCLEAN, -ELOOP, -ENOENT)) + /* Ignore generated/transient/missing/invalid units when applying preset, propagate other errors. + * Coordinate with unit_file_dump_changes() above. */ return r; } } - return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes); + return execute_preset(scope, file_flags, &plus, &minus, &paths, config_path, NULL, mode, changes, n_changes); } static UnitFileList* unit_file_list_free_one(UnitFileList *f) { @@ -3493,6 +3513,7 @@ static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] [UNIT_FILE_IS_MASKED] = "masked", [UNIT_FILE_IS_DANGLING] = "dangling", [UNIT_FILE_DESTINATION_NOT_PRESENT] = "destination not present", + [UNIT_FILE_AUXILIARY_FAILED] = "auxiliary unit failed", }; DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, int); diff --git a/src/shared/install.h b/src/shared/install.h index 7ab0a871e0..c3a0249f5f 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -33,15 +33,17 @@ enum { UNIT_FILE_IS_MASKED, UNIT_FILE_IS_DANGLING, UNIT_FILE_DESTINATION_NOT_PRESENT, + UNIT_FILE_AUXILIARY_FAILED, _UNIT_FILE_CHANGE_TYPE_MAX, _UNIT_FILE_CHANGE_TYPE_INVALID = -EINVAL, }; enum UnitFileFlags { - UNIT_FILE_RUNTIME = 1 << 0, /* Public API via DBUS, do not change */ - UNIT_FILE_FORCE = 1 << 1, /* Public API via DBUS, do not change */ - UNIT_FILE_PORTABLE = 1 << 2, /* Public API via DBUS, do not change */ - UNIT_FILE_DRY_RUN = 1 << 3, + UNIT_FILE_RUNTIME = 1 << 0, /* Public API via DBUS, do not change */ + UNIT_FILE_FORCE = 1 << 1, /* Public API via DBUS, do not change */ + UNIT_FILE_PORTABLE = 1 << 2, /* Public API via DBUS, do not change */ + UNIT_FILE_DRY_RUN = 1 << 3, + UNIT_FILE_IGNORE_AUXILIARY_FAILURE = 1 << 4, _UNIT_FILE_FLAGS_MASK_PUBLIC = UNIT_FILE_RUNTIME|UNIT_FILE_PORTABLE|UNIT_FILE_FORCE, };