#include "build.h"
#include "bus-polkit.h"
#include "conf-files.h"
+#include "conf-parser.h"
#include "constants.h"
#include "discover-image.h"
#include "dissect-image.h"
#include "strv.h"
#include "sysupdate.h"
#include "sysupdate-cleanup.h"
+#include "sysupdate-config.h"
#include "sysupdate-feature.h"
#include "sysupdate-instance.h"
#include "sysupdate-target.h"
#define CONTEXT_NULL \
(Context) { \
+ .component_enabled = true, \
.sync = true, \
.instances_max = UINT64_MAX, \
.verify = -1, \
c->root = mfree(c->root);
c->image = mfree(c->image);
c->component = mfree(c->component);
+ c->component_description = mfree(c->component_description);
+ c->component_documentation = strv_free(c->component_documentation);
c->image_policy = image_policy_free(c->image_policy);
c->transfer_source = mfree(c->transfer_source);
return 0;
}
+static int read_component(Context *c) {
+ int r;
+
+ assert(c);
+
+ /* Read a component description file, but only if we actually operate on a component */
+ if (c->definitions || !c->component)
+ return 0;
+
+ _cleanup_free_ char *j = strjoin("sysupdate.", c->component, ".component");
+ if (!j)
+ return log_oom();
+
+ ConfigTableItem table[] = {
+ { "Component", "Description", config_parse_string, 0, &c->component_description },
+ { "Component", "Documentation", config_parse_url_specifiers_many, 0, &c->component_documentation },
+ { "Component", "Enabled", config_parse_bool, 0, &c->component_enabled },
+ {}
+ };
+
+ r = config_parse_standard_file_with_dropins_full(
+ c->root,
+ /* root_fd= */ -EBADF,
+ j,
+ "Component\0",
+ config_item_table_lookup, table,
+ CONFIG_PARSE_WARN,
+ /* userdata= */ (void *) c->root,
+ /* ret_stats_by_path= */ NULL,
+ /* ret_dropin_files= */ NULL);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
typedef enum ReadDefinitionsFlags {
- READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS = 1 << 0,
- READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS = 1 << 1,
+ READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS = 1 << 0, /* fail unless there's at least one enabled transfer */
+ READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS = 1 << 1, /* fail unless there's at least one transfer */
+ READ_DEFINITIONS_REQUIRES_ENABLED_COMPONENT = 1 << 2, /* fail if component is disabled */
} ReadDefinitionsFlags;
static int context_read_definitions(Context *c, const char* node, ReadDefinitionsFlags flags) {
if (!dirs)
return log_oom();
+ r = read_component(c);
+ if (r < 0)
+ return r;
+
r = read_features(c, (const char**) dirs);
if (r < 0)
return r;
"No transfer definitions found.");
}
+ if (FLAGS_SET(flags, READ_DEFINITIONS_REQUIRES_ENABLED_COMPONENT) && !c->component_enabled)
+ return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN), "Component is disabled.");
+
return 0;
}
static int context_load_online(
Context *context,
- ProcessImageFlags process_image_flags) {
+ ProcessImageFlags process_image_flags,
+ ReadDefinitionsFlags read_definitions_flags) {
+
int r;
assert(context);
r = context_load_offline(
context,
process_image_flags,
- READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS|READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS);
+ read_definitions_flags);
if (r < 0)
return r;
* syntactically validated by dispatch_target_identifier(), but might still point to components which don’t
* exist, images which the user isn’t privileged to access, etc. This function validates the TargetIdentifier
* against an enumerated list of known targets, which are safe to update without additional permissions. */
-static int context_load_online_from_target(Context *context, ProcessImageFlags process_image_flags) {
+static int context_load_online_from_target(
+ Context *context,
+ ProcessImageFlags process_image_flags,
+ ReadDefinitionsFlags read_definitions_flags) {
int r;
assert(context);
assert_not_reached();
}
- return context_load_online(context, process_image_flags);
+ return context_load_online(context, process_image_flags, read_definitions_flags);
}
static int context_on_acquire_progress(const Transfer *t, const Instance *inst, unsigned percentage) {
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, PROCESS_IMAGE_READ_ONLY);
+ r = context_load_online(
+ &context,
+ PROCESS_IMAGE_READ_ONLY,
+ READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS|
+ READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS);
if (r < 0)
return r;
r = context_load_online(
&context,
- PROCESS_IMAGE_READ_ONLY);
+ PROCESS_IMAGE_READ_ONLY,
+ READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS|
+ READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS);
if (r < 0)
return r;
/* CheckNew is always online */
context.offline = false;
- r = context_load_online_from_target(&context, PROCESS_IMAGE_READ_ONLY);
+ r = context_load_online_from_target(
+ &context,
+ PROCESS_IMAGE_READ_ONLY,
+ READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS|
+ READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS);
if (r == -ENOENT)
return sd_varlink_error(link, "io.systemd.SysUpdate.NoSuchTarget", NULL);
if (r < 0)
r = context_load_online(
&context,
- /* process_image_flags= */ 0);
+ /* process_image_flags= */ 0,
+ READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS|
+ READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS|
+ READ_DEFINITIONS_REQUIRES_ENABLED_COMPONENT);
if (r < 0) {
if (r != -ENOENT)
return r;
r = context_load_offline(
&context,
/* process_image_flags= */ 0,
- READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS|READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS);
+ READ_DEFINITIONS_REQUIRES_ENABLED_TRANSFERS|
+ READ_DEFINITIONS_REQUIRES_ANY_TRANSFERS|
+ READ_DEFINITIONS_REQUIRES_ENABLED_COMPONENT);
if (r < 0)
return r;