diff --git a/src/sysupdate/sysupdate-cleanup.c b/src/sysupdate/sysupdate-cleanup.c index 5c517e401ac..2d0229423d5 100644 --- a/src/sysupdate/sysupdate-cleanup.c +++ b/src/sysupdate/sysupdate-cleanup.c @@ -77,14 +77,14 @@ static int context_installdb_acquire_fd(Context *c, bool make) { c->installdb_fd = chase_and_open( p, - arg_root, + c->root, flags, O_DIRECTORY|O_CLOEXEC|(make ? O_CREAT : 0), /* ret_path= */ NULL); if (c->installdb_fd == -ENOENT && !make) return 0; if (c->installdb_fd < 0) - return log_error_errno(c->installdb_fd, "Failed to open install database '%s%s': %m", empty_or_root(arg_root) ? "" : arg_root, p); + return log_error_errno(c->installdb_fd, "Failed to open install database '%s%s': %m", empty_or_root(c->root) ? "" : c->root, p); return 1; } @@ -128,8 +128,8 @@ int context_installdb_record( if (strv_isempty(patterns)) return 0; - /* The provided path comes with arg_root prefixed. Strip it here again */ - const char *p = arg_root ? ASSERT_PTR(path_startswith(path, arg_root)) : path; + /* The provided path comes with c->root prefixed. Strip it here again */ + const char *p = c->root ? ASSERT_PTR(path_startswith(path, c->root)) : path; r = context_installdb_acquire_fd(c, /* make= */ true); if (r < 0) @@ -336,7 +336,7 @@ static int context_installdb_process_entry( /* NB: We set CHASE_PROHIBIT_SYMLINKS because the path was normalized by the writer of the entry * already, and if it isn't anymore, then something is fishy. */ - _cleanup_close_ int dir_fd = chase_and_open(path, arg_root, CHASE_MUST_BE_DIRECTORY|CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, O_DIRECTORY|O_CLOEXEC, /* ret_path= */ NULL); + _cleanup_close_ int dir_fd = chase_and_open(path, c->root, CHASE_MUST_BE_DIRECTORY|CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, O_DIRECTORY|O_CLOEXEC, /* ret_path= */ NULL); if (dir_fd == -ENOENT) { log_debug("Install database path '%s' does not exist, expunging database entry.", path); return 0; @@ -399,14 +399,15 @@ int installdb_cleanup_component(Context *context) { return ret; } -int installdb_list_components(char ***ret) { +int installdb_list_components(Context *context, char ***ret) { int r; + assert(context); assert(ret); _cleanup_close_ int dir_fd = chase_and_open( "/var/lib/systemd/sysupdate", - arg_root, + context->root, CHASE_MUST_BE_DIRECTORY|CHASE_PREFIX_ROOT, O_DIRECTORY|O_CLOEXEC, /* ret_path= */ NULL); diff --git a/src/sysupdate/sysupdate-cleanup.h b/src/sysupdate/sysupdate-cleanup.h index cb3c7b64445..d7b261e35bc 100644 --- a/src/sysupdate/sysupdate-cleanup.h +++ b/src/sysupdate/sysupdate-cleanup.h @@ -6,4 +6,4 @@ int context_installdb_record(Context *c, const char *path, char **patterns); int installdb_cleanup_component(Context *context); -int installdb_list_components(char ***ret); +int installdb_list_components(Context *context, char ***ret); diff --git a/src/sysupdate/sysupdate-feature.c b/src/sysupdate/sysupdate-feature.c index 795d4ef90a3..d67b61859cf 100644 --- a/src/sysupdate/sysupdate-feature.c +++ b/src/sysupdate/sysupdate-feature.c @@ -54,6 +54,7 @@ static int config_parse_url_specifiers( void *data, void *userdata) { char **s = ASSERT_PTR(data); + const char *root = ASSERT_PTR(userdata); _cleanup_free_ char *resolved = NULL; int r; @@ -64,7 +65,7 @@ static int config_parse_url_specifiers( return 0; } - r = specifier_printf(rvalue, NAME_MAX, specifier_table, arg_root, NULL, &resolved); + r = specifier_printf(rvalue, NAME_MAX, specifier_table, root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in %s=, ignoring: %s", lvalue, rvalue); @@ -80,7 +81,7 @@ static int config_parse_url_specifiers( return free_and_replace(*s, resolved); } -int feature_read_definition(Feature *f, const char *path, const char *const *dirs) { +int feature_read_definition(Feature *f, const char *root, const char *path, const char *const *dirs) { assert(f); ConfigTableItem table[] = { @@ -105,12 +106,12 @@ int feature_read_definition(Feature *f, const char *path, const char *const *dir STRV_MAKE_CONST(path), dirs, strjoina(filename, ".d"), - arg_root, + root, /* root_fd= */ -EBADF, "Feature\0", config_item_table_lookup, table, CONFIG_PARSE_WARN, - /* userdata= */ NULL, + (void *) root, /* stats_by_path= */ NULL, /* drop_in_files= */ NULL); if (r < 0) diff --git a/src/sysupdate/sysupdate-feature.h b/src/sysupdate/sysupdate-feature.h index b42df5c27e6..7d7495087c5 100644 --- a/src/sysupdate/sysupdate-feature.h +++ b/src/sysupdate/sysupdate-feature.h @@ -22,4 +22,4 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Feature*, feature_unref); extern const struct hash_ops feature_hash_ops; -int feature_read_definition(Feature *f, const char *path, const char *const *conf_file_dirs); +int feature_read_definition(Feature *f, const char *root, const char *path, const char *const *conf_file_dirs); diff --git a/src/sysupdate/sysupdate-transfer.c b/src/sysupdate/sysupdate-transfer.c index f7e257e041a..f2a4377e1e9 100644 --- a/src/sysupdate/sysupdate-transfer.c +++ b/src/sysupdate/sysupdate-transfer.c @@ -122,11 +122,12 @@ static int config_parse_protect_version( _cleanup_free_ char *resolved = NULL; char ***protected_versions = ASSERT_PTR(data); + Transfer *t = ASSERT_PTR(userdata); int r; assert(rvalue); - r = specifier_printf(rvalue, NAME_MAX, specifier_table, arg_root, NULL, &resolved); + r = specifier_printf(rvalue, NAME_MAX, specifier_table, t->context->root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in ProtectVersion=, ignoring: %s", rvalue); @@ -160,11 +161,12 @@ static int config_parse_min_version( _cleanup_free_ char *resolved = NULL; char **version = ASSERT_PTR(data); + Transfer *t = ASSERT_PTR(userdata); int r; assert(rvalue); - r = specifier_printf(rvalue, NAME_MAX, specifier_table, arg_root, NULL, &resolved); + r = specifier_printf(rvalue, NAME_MAX, specifier_table, t->context->root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in MinVersion=, ignoring: %s", rvalue); @@ -192,6 +194,7 @@ static int config_parse_url_specifiers( void *data, void *userdata) { char ***s = ASSERT_PTR(data); + Transfer *t = ASSERT_PTR(userdata); _cleanup_free_ char *resolved = NULL; int r; @@ -202,7 +205,7 @@ static int config_parse_url_specifiers( return 0; } - r = specifier_printf(rvalue, NAME_MAX, specifier_table, arg_root, NULL, &resolved); + r = specifier_printf(rvalue, NAME_MAX, specifier_table, t->context->root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in %s=, ignoring: %s", lvalue, rvalue); @@ -236,11 +239,12 @@ static int config_parse_current_symlink( _cleanup_free_ char *resolved = NULL; char **current_symlink = ASSERT_PTR(data); + Transfer *t = ASSERT_PTR(userdata); int r; assert(rvalue); - r = specifier_printf(rvalue, NAME_MAX, specifier_table, arg_root, NULL, &resolved); + r = specifier_printf(rvalue, NAME_MAX, specifier_table, t->context->root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in CurrentSymlink=, ignoring: %s", rvalue); @@ -307,6 +311,7 @@ static int config_parse_resource_pattern( void *userdata) { char ***patterns = ASSERT_PTR(data); + Transfer *t = ASSERT_PTR(userdata); int r; assert(rvalue); @@ -328,7 +333,7 @@ static int config_parse_resource_pattern( if (r == 0) break; - r = specifier_printf(word, NAME_MAX, specifier_table, arg_root, NULL, &resolved); + r = specifier_printf(word, NAME_MAX, specifier_table, t->context->root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in MatchPattern=, ignoring: %s", rvalue); @@ -361,6 +366,7 @@ static int config_parse_resource_path( void *userdata) { _cleanup_free_ char *resolved = NULL; Resource *rr = ASSERT_PTR(data); + Transfer *t = ASSERT_PTR(userdata); int r; assert(rvalue); @@ -371,7 +377,7 @@ static int config_parse_resource_path( return 0; } - r = specifier_printf(rvalue, PATH_MAX-1, specifier_table, arg_root, NULL, &resolved); + r = specifier_printf(rvalue, PATH_MAX-1, specifier_table, t->context->root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in Path=, ignoring: %s", rvalue); @@ -549,14 +555,14 @@ int transfer_read_definition(Transfer *t, const char *path, const char **dirs, H STRV_MAKE_CONST(path), dirs, strjoina(filename, ".d"), - arg_root, + t->context->root, /* root_fd= */ -EBADF, "Transfer\0" "Source\0" "Target\0", config_item_table_lookup, table, CONFIG_PARSE_WARN, - /* userdata= */ NULL, + t, /* stats_by_path= */ NULL, /* drop_in_files= */ NULL); if (r < 0) @@ -613,7 +619,7 @@ int transfer_read_definition(Transfer *t, const char *path, const char **dirs, H return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), "Source specification lacks Path=."); - if (t->source.path_relative_to == PATH_RELATIVE_TO_EXPLICIT && !arg_transfer_source) + if (t->source.path_relative_to == PATH_RELATIVE_TO_EXPLICIT && !t->context->transfer_source) return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), "PathRelativeTo=explicit requires --transfer-source= to be specified."); @@ -682,7 +688,7 @@ int transfer_resolve_paths( assert(t); - r = resource_resolve_path(&t->source, root, arg_transfer_source, node); + r = resource_resolve_path(&t->source, root, t->context->transfer_source, node); if (r < 0) return r; @@ -849,7 +855,7 @@ int transfer_vacuum( /* Second, calculate how many instances to keep, based on the instance limit — but keep at least one */ - instances_max = arg_instances_max != UINT64_MAX ? arg_instances_max : t->instances_max; + instances_max = t->context->instances_max != UINT64_MAX ? t->context->instances_max : t->instances_max; assert(instances_max >= 1); if (instances_max == UINT64_MAX) /* Keep infinite instances? */ limit = UINT64_MAX; @@ -1369,7 +1375,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i, InstanceMetadata *f, Tra SYSTEMD_IMPORT_PATH, "raw", "--direct", /* just copy/unpack the specified file, don't do anything else */ - arg_sync ? "--sync=yes" : "--sync=no", + t->context->sync ? "--sync=yes" : "--sync=no", i->path, t->temporary_partial_path), t, i, cb, userdata); @@ -1386,7 +1392,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i, InstanceMetadata *f, Tra "--direct", /* just copy/unpack the specified file, don't do anything else */ "--offset", offset, "--size-max", max_size, - arg_sync ? "--sync=yes" : "--sync=no", + t->context->sync ? "--sync=yes" : "--sync=no", i->path, t->target.path), t, i, cb, userdata); @@ -1409,7 +1415,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i, InstanceMetadata *f, Tra SYSTEMD_IMPORT_FS_PATH, "run", "--direct", /* just untar the specified file, don't do anything else */ - arg_sync ? "--sync=yes" : "--sync=no", + t->context->sync ? "--sync=yes" : "--sync=no", t->target.type == RESOURCE_SUBVOLUME ? "--btrfs-subvol=yes" : "--btrfs-subvol=no", i->path, t->temporary_partial_path), @@ -1426,7 +1432,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i, InstanceMetadata *f, Tra SYSTEMD_IMPORT_PATH, "tar", "--direct", /* just untar the specified file, don't do anything else */ - arg_sync ? "--sync=yes" : "--sync=no", + t->context->sync ? "--sync=yes" : "--sync=no", t->target.type == RESOURCE_SUBVOLUME ? "--btrfs-subvol=yes" : "--btrfs-subvol=no", i->path, t->temporary_partial_path), @@ -1447,7 +1453,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i, InstanceMetadata *f, Tra "raw", "--direct", /* just download the specified URL, don't download anything else */ "--verify", digest, /* validate by explicit SHA256 sum */ - arg_sync ? "--sync=yes" : "--sync=no", + t->context->sync ? "--sync=yes" : "--sync=no", i->path, t->temporary_partial_path), t, i, cb, userdata); @@ -1465,7 +1471,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i, InstanceMetadata *f, Tra "--verify", digest, /* validate by explicit SHA256 sum */ "--offset", offset, "--size-max", max_size, - arg_sync ? "--sync=yes" : "--sync=no", + t->context->sync ? "--sync=yes" : "--sync=no", i->path, t->target.path), t, i, cb, userdata); @@ -1487,7 +1493,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i, InstanceMetadata *f, Tra "--direct", /* just download the specified URL, don't download anything else */ "--verify", digest, /* validate by explicit SHA256 sum */ t->target.type == RESOURCE_SUBVOLUME ? "--btrfs-subvol=yes" : "--btrfs-subvol=no", - arg_sync ? "--sync=yes" : "--sync=no", + t->context->sync ? "--sync=yes" : "--sync=no", i->path, t->temporary_partial_path), t, i, cb, userdata); @@ -1528,7 +1534,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i, InstanceMetadata *f, Tra } /* Synchronize */ - if (arg_sync && need_sync) { + if (t->context->sync && need_sync) { if (t->target.type == RESOURCE_REGULAR_FILE) r = fsync_path_and_parent_at(AT_FDCWD, t->temporary_partial_path); else { diff --git a/src/sysupdate/sysupdate.c b/src/sysupdate/sysupdate.c index 74fe267036c..3232ab6e377 100644 --- a/src/sysupdate/sysupdate.c +++ b/src/sysupdate/sysupdate.c @@ -43,12 +43,12 @@ #include "verbs.h" static char *arg_definitions = NULL; -bool arg_sync = true; -uint64_t arg_instances_max = UINT64_MAX; +static bool arg_sync = true; +static uint64_t arg_instances_max = UINT64_MAX; static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF; static PagerFlags arg_pager_flags = 0; static bool arg_legend = true; -char *arg_root = NULL; +static char *arg_root = NULL; static char *arg_image = NULL; static bool arg_reboot = false; static int arg_cleanup = -1; @@ -57,7 +57,7 @@ static bool arg_component_all = false; static int arg_verify = -1; static ImagePolicy *arg_image_policy = NULL; static bool arg_offline = false; -char *arg_transfer_source = NULL; +static char *arg_transfer_source = NULL; STATIC_DESTRUCTOR_REGISTER(arg_definitions, freep); STATIC_DESTRUCTOR_REGISTER(arg_root, freep); @@ -74,14 +74,16 @@ const Specifier specifier_table[] = { #define CONTEXT_NULL \ (Context) { \ + .sync = true, \ + .instances_max = UINT64_MAX, \ + .verify = -1, \ + .cleanup = -1, \ .installdb_fd = -EBADF, \ } void context_done(Context *c) { assert(c); - c->component = mfree(c->component); - c->mounted_dir = umount_and_rmdir_and_free(c->mounted_dir); c->loop_device = loop_device_unref(c->loop_device); @@ -105,6 +107,51 @@ void context_done(Context *c) { c->web_cache = hashmap_free(c->web_cache); c->installdb_fd = safe_close(c->installdb_fd); + + c->definitions = mfree(c->definitions); + c->root = mfree(c->root); + c->image = mfree(c->image); + c->component = mfree(c->component); + c->image_policy = image_policy_free(c->image_policy); + c->transfer_source = mfree(c->transfer_source); +} + +static int context_from_cmdline(Context *ret) { + assert(ret); + + _cleanup_(context_done) Context context = CONTEXT_NULL; + + context.instances_max = arg_instances_max; + context.sync = arg_sync; + context.reboot = arg_reboot; + context.verify = arg_verify; + context.offline = arg_offline; + context.cleanup = arg_cleanup; + context.component_all = arg_component_all; + + if (strdup_to(&context.definitions, arg_definitions) < 0) + return log_oom(); + + if (strdup_to(&context.root, arg_root) < 0) + return log_oom(); + + if (strdup_to(&context.image, arg_image) < 0) + return log_oom(); + + if (strdup_to(&context.component, arg_component) < 0) + return log_oom(); + + if (strdup_to(&context.transfer_source, arg_transfer_source) < 0) + return log_oom(); + + if (arg_image_policy) { + context.image_policy = image_policy_copy(arg_image_policy); + if (!context.image_policy) + return log_oom(); + } + + *ret = TAKE_GENERIC(context, Context, CONTEXT_NULL); + return 0; } static DEFINE_POINTER_ARRAY_FREE_FUNC(Transfer*, transfer_free); @@ -128,7 +175,7 @@ static int read_definitions( assert(dirs); assert(suffix); - r = conf_files_list_strv_full(suffix, arg_root, + r = conf_files_list_strv_full(suffix, c->root, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED|CONF_FILES_WARN, dirs, &files, &n_files); if (r < 0) @@ -147,7 +194,7 @@ static int read_definitions( if (r < 0) return r; - r = transfer_resolve_paths(t, arg_root, node); + r = transfer_resolve_paths(t, c->root, node); if (r < 0) return r; @@ -178,8 +225,8 @@ static int context_read_definitions(Context *c, const char* node, ReadDefinition assert(c); - if (arg_definitions) - dirs = strv_new(arg_definitions); + if (c->definitions) + dirs = strv_new(c->definitions); else if (c->component) { char **l = CONF_PATHS_STRV(""); size_t i = 0; @@ -207,7 +254,7 @@ static int context_read_definitions(Context *c, const char* node, ReadDefinition CLEANUP_ARRAY(files, n_files, conf_file_free_array); - r = conf_files_list_strv_full(".feature", arg_root, + r = conf_files_list_strv_full(".feature", c->root, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED|CONF_FILES_WARN, (const char**) dirs, &files, &n_files); if (r < 0) @@ -221,7 +268,7 @@ static int context_read_definitions(Context *c, const char* node, ReadDefinition if (!f) return log_oom(); - r = feature_read_definition(f, e->result, (const char**) dirs); + r = feature_read_definition(f, c->root, e->result, (const char**) dirs); if (r < 0) return r; @@ -271,7 +318,7 @@ static int context_load_installed_instances(Context *c) { r = resource_load_instances( &t->target, - arg_verify >= 0 ? arg_verify : t->verify, + c->verify >= 0 ? c->verify : t->verify, &c->web_cache); if (r < 0) return r; @@ -282,7 +329,7 @@ static int context_load_installed_instances(Context *c) { r = resource_load_instances( &t->target, - arg_verify >= 0 ? arg_verify : t->verify, + c->verify >= 0 ? c->verify : t->verify, &c->web_cache); if (r < 0) return r; @@ -303,7 +350,7 @@ static int context_load_available_instances(Context *c) { r = resource_load_instances( &t->source, - arg_verify >= 0 ? arg_verify : t->verify, + c->verify >= 0 ? c->verify : t->verify, &c->web_cache); if (r < 0) return r; @@ -527,7 +574,7 @@ static int context_discover_update_sets(Context *c) { if (r < 0) return r; - if (!arg_offline) { + if (!c->offline) { log_info("Determining available update sets%s", glyph(GLYPH_ELLIPSIS)); r = context_discover_update_sets_by_flag(c, UPDATE_AVAILABLE); @@ -941,16 +988,16 @@ static int process_image( assert(c); - if (!arg_image) + if (!c->image) return 0; - assert(!arg_root); + assert(!c->root); assert(!c->mounted_dir); assert(!c->loop_device); r = mount_image_privately_interactively( - arg_image, - arg_image_policy, + c->image, + c->image_policy, (FLAGS_SET(flags, PROCESS_IMAGE_READ_ONLY) ? DISSECT_IMAGE_READ_ONLY : 0) | DISSECT_IMAGE_FSCK | DISSECT_IMAGE_MKDIR | @@ -966,8 +1013,8 @@ static int process_image( if (r < 0) return r; - arg_root = strdup(mounted_dir); - if (!arg_root) + c->root = strdup(mounted_dir); + if (!c->root) return log_oom(); c->mounted_dir = TAKE_PTR(mounted_dir); @@ -978,7 +1025,6 @@ static int process_image( static int context_load_offline( Context *context, - const char *component, ProcessImageFlags process_image_flags, ReadDefinitionsFlags read_definitions_flags) { int r; @@ -988,10 +1034,6 @@ static int context_load_offline( /* Sets up a context object and initializes everything we can initialize offline, i.e. without * checking on the update source (i.e. the Internet) what versions are available */ - r = free_and_strdup_warn(&context->component, component); - if (r < 0) - return r; - r = process_image(context, process_image_flags); if (r < 0) return r; @@ -1009,7 +1051,6 @@ static int context_load_offline( static int context_load_online( Context *context, - const char *component, ProcessImageFlags process_image_flags) { int r; @@ -1020,13 +1061,12 @@ static int context_load_online( r = context_load_offline( context, - component, process_image_flags, READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS|READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS); if (r < 0) return r; - if (!arg_offline) { + if (!context->offline) { r = context_load_available_instances(context); if (r < 0) return r; @@ -1146,7 +1186,7 @@ static int context_acquire( if (r < 0) return r; - if (arg_sync) + if (c->sync) sync(); (void) sd_notifyf(/* unset_environment= */ false, @@ -1171,7 +1211,7 @@ static int context_acquire( return r; } - if (arg_sync) + if (c->sync) sync(); return 1; @@ -1294,7 +1334,7 @@ static int context_notify_subscribers(Context *c, UpdateSet *us) { _cleanup_(sd_json_variant_unrefp) sd_json_variant *params = NULL; r = sd_json_buildo( ¶ms, - SD_JSON_BUILD_PAIR_CONDITION(!!arg_component, "component", SD_JSON_BUILD_STRING(arg_component)), + SD_JSON_BUILD_PAIR_CONDITION(!!c->component, "component", SD_JSON_BUILD_STRING(c->component)), SD_JSON_BUILD_PAIR_CONDITION(!!us, "version", SD_JSON_BUILD_STRING(us ? us->version : NULL)), SD_JSON_BUILD_PAIR_CONDITION(!!resources, "resources", SD_JSON_BUILD_VARIANT(resources))); if (r < 0) @@ -1354,14 +1394,14 @@ static int context_install( !inst->is_pending) continue; - r = transfer_install_instance(t, inst, arg_root); + r = transfer_install_instance(t, inst, c->root); if (r < 0) return r; } log_info("%s Successfully installed update '%s'.", glyph(GLYPH_SPARKLES), us->version); - if (!arg_root) + if (!c->root) (void) context_notify_subscribers(c, us); (void) sd_notifyf(/* unset_environment= */ false, @@ -1384,13 +1424,14 @@ static int verb_list(int argc, char *argv[], uintptr_t _data, void *userdata) { assert(argc <= 2); version = argc >= 2 ? argv[1] : NULL; - if (arg_component_all) + r = context_from_cmdline(&context); + if (r < 0) + return r; + + if (context.component_all) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "--component-all currently not supported for '%s'.", argv[0]); - r = context_load_online( - &context, - arg_component, - PROCESS_IMAGE_READ_ONLY); + r = context_load_online(&context, PROCESS_IMAGE_READ_ONLY); if (r < 0) return r; @@ -1455,12 +1496,15 @@ static int verb_features(int argc, char *argv[], uintptr_t _data, void *userdata assert(argc <= 2); feature_id = argc >= 2 ? argv[1] : NULL; - if (arg_component_all) + r = context_from_cmdline(&context); + if (r < 0) + return r; + + if (context.component_all) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "--component-all currently not supported for '%s'.", argv[0]); r = context_load_offline( &context, - arg_component, PROCESS_IMAGE_READ_ONLY, READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS); if (r < 0) @@ -1588,12 +1632,15 @@ static int verb_check_new(int argc, char *argv[], uintptr_t _data, void *userdat assert(argc <= 1); - if (arg_component_all) + r = context_from_cmdline(&context); + if (r < 0) + return r; + + if (context.component_all) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "--component-all currently not supported for '%s'.", argv[0]); r = context_load_online( &context, - arg_component, PROCESS_IMAGE_READ_ONLY); if (r < 0) return r; @@ -1638,17 +1685,21 @@ static int verb_update_impl(int argc, char **argv, UpdateActionFlags action_flag assert(argc <= 2); version = argc >= 2 ? argv[1] : NULL; - if (arg_component_all) + r = context_from_cmdline(&context); + if (r < 0) + return r; + + if (context.component_all) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "--component-all currently not supported for '%s'.", argv[0]); - if (arg_instances_max < 2) + if (context.instances_max < 2) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --instances-max argument must be >= 2 while updating"); - if (arg_reboot) { + if (context.reboot) { /* If automatic reboot on completion is requested, let's first determine the currently booted image */ - r = parse_os_release(arg_root, "IMAGE_VERSION", &booted_version); + r = parse_os_release(context.root, "IMAGE_VERSION", &booted_version); if (r < 0) return log_error_errno(r, "Failed to parse /etc/os-release: %m"); if (!booted_version) @@ -1660,7 +1711,6 @@ static int verb_update_impl(int argc, char **argv, UpdateActionFlags action_flag r = context_load_online( &context, - arg_component, /* process_image_flags= */ 0); if (r < 0) { if (r != -ENOENT) @@ -1696,13 +1746,13 @@ static int verb_update_impl(int argc, char **argv, UpdateActionFlags action_flag } } - if (arg_cleanup > 0) + if (context.cleanup > 0) RET_GATHER(ret, installdb_cleanup_component(&context)); if (installed) { /* We installed something, yay */ - if (arg_reboot) { + if (context.reboot) { assert(applied); assert(booted_version); @@ -1746,16 +1796,19 @@ static int verb_vacuum(int argc, char *argv[], uintptr_t _data, void *userdata) assert(argc <= 1); - if (arg_component_all) + r = context_from_cmdline(&context); + if (r < 0) + return r; + + if (context.component_all) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "--component-all currently not supported for '%s'.", argv[0]); - if (arg_instances_max < 1) + if (context.instances_max < 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --instances-max argument must be >= 1 while vacuuming"); r = context_load_offline( &context, - arg_component, /* process_image_flags= */ 0, READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS); if (r < 0) @@ -1775,17 +1828,20 @@ static int verb_pending_or_reboot(int argc, char *argv[], uintptr_t _data, void assert(argc == 1); - if (arg_image || arg_root) + r = context_from_cmdline(&context); + if (r < 0) + return r; + + if (context.image || context.root) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --root=/--image= switches may not be combined with the '%s' operation.", argv[0]); - if (arg_component || arg_component_all) + if (context.component || context.component_all) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --component= and --component-all switches may not be combined with the '%s' operation, which only applies to the booted OS version.", argv[0]); r = context_load_offline( &context, - arg_component, /* process_image_flags= */ 0, READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS|READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS); if (r < 0) @@ -1799,8 +1855,8 @@ static int verb_pending_or_reboot(int argc, char *argv[], uintptr_t _data, void if (!context.newest_installed) return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "Couldn't find any suitable installed versions."); - r = parse_os_release(arg_root, "IMAGE_VERSION", &booted_version); - if (r < 0) /* yes, arg_root is NULL here, but we have to pass something, and it's a lot more readable + r = parse_os_release(context.root, "IMAGE_VERSION", &booted_version); + if (r < 0) /* yes, context.root is NULL here, but we have to pass something, and it's a lot more readable * if we see what the first argument is about */ return log_error_errno(r, "Failed to parse /etc/os-release: %m"); if (!booted_version) @@ -1838,28 +1894,31 @@ static int verb_components(int argc, char *argv[], uintptr_t _data, void *userda assert(argc <= 1); - if (arg_component_all) + r = context_from_cmdline(&context); + if (r < 0) + return r; + + if (context.component_all) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "--component-all currently not supported for '%s'.", argv[0]); r = context_load_offline( &context, - arg_component, /* process_image_flags= */ 0, /* read_definitions_flags= */ 0); if (r < 0) return r; _cleanup_strv_free_ char **z = NULL; - r = get_component_list(arg_root, &z); + r = get_component_list(context.root, &z); if (r < 0) return log_error_errno(r, "Failed to enumerate components: %m"); /* Does the system have at least one transfer file in /etc/sysupdate.d, which can be considered a * TARGET_HOST? See target_get_argument() in sysupdated.c */ - has_default_component = (!arg_definitions && + has_default_component = (!context.definitions && !context.component && - !arg_root && - !arg_image && + !context.root && + !context.image && context.n_transfers > 0); if (!sd_json_format_enabled(arg_json_format_flags)) { @@ -1897,12 +1956,15 @@ static int verb_cleanup(int argc, char *argv[], uintptr_t _data, void *userdata) assert(argc <= 1); - if (arg_cleanup == 0) + r = context_from_cmdline(&context); + if (r < 0) + return r; + + if (context.cleanup == 0) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invocation of 'cleanup' with --cleanup=no is contradictory, refusing."); r = context_load_offline( &context, - arg_component, /* process_image_flags= */ 0, /* read_definitions_flags= */ 0); if (r < 0) @@ -1911,18 +1973,27 @@ static int verb_cleanup(int argc, char *argv[], uintptr_t _data, void *userdata) int ret = 0; RET_GATHER(ret, installdb_cleanup_component(&context)); - if (arg_component_all) { + if (context.component_all) { _cleanup_strv_free_ char **z = NULL; - r = installdb_list_components(&z); + r = installdb_list_components(&context, &z); if (r < 0) return log_error_errno(r, "Failed to enumerate components: %m"); STRV_FOREACH(i, z) { _cleanup_(context_done) Context component_context = CONTEXT_NULL; + r = context_from_cmdline(&component_context); + if (r < 0) + return r; + + /* Override the component with our iter. This needs to be done in a fresh Context + * as the installdb_fd and other state are specific to the component. */ + r = free_and_strdup_warn(&component_context.component, *i); + if (r < 0) + return r; + r = context_load_offline( &component_context, - *i, /* process_image_flags= */ 0, /* read_definitions_flags= */ 0); if (r < 0) diff --git a/src/sysupdate/sysupdate.h b/src/sysupdate/sysupdate.h index be6b46720d1..0d0a8e9fbfa 100644 --- a/src/sysupdate/sysupdate.h +++ b/src/sysupdate/sysupdate.h @@ -5,8 +5,22 @@ #include "sysupdate-forward.h" typedef struct Context { + /* Parameters/Command line arguments: */ + char *definitions; + bool sync; + uint64_t instances_max; + char *root; + char *image; + bool reboot; + int cleanup; char *component; + bool component_all; + int verify; + ImagePolicy *image_policy; + bool offline; + char *transfer_source; + /* Loaded state: */ LoopDevice *loop_device; char *mounted_dir; @@ -30,9 +44,4 @@ typedef struct Context { void context_done(Context *c); -extern bool arg_sync; -extern uint64_t arg_instances_max; -extern char *arg_root; -extern char *arg_transfer_source; - extern const Specifier specifier_table[];