From: Philip Withnall Date: Fri, 29 May 2026 13:40:08 +0000 (+0100) Subject: sysupdate: Move global arg_* variables into Context X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f91ac1ac260aafdbd0c0c2365f0ad705f3769018;p=thirdparty%2Fsystemd.git sysupdate: Move global arg_* variables into Context This is another step towards varlinkifying the program, as it means the various verb implementations are no longer relying on global state from the command line. As part of this, move init of the `Context` struct into a new `context_from_cmdline()` function. Additionally pass some context into config parsing `userdata` arguments, as various config parsers were using `arg_root` via a sneaky `extern`. This introduces no functional changes. --- 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[];