Merge pull request #22656 from keszybz/portablectl-method2

portable: add return parameter to GetImageMetadataWithExtensions
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2022-03-08 13:26:33 +01:00
committed by GitHub
6 changed files with 119 additions and 98 deletions
+6 -7
View File
@@ -21,14 +21,13 @@ typedef struct PortableMetadata {
#define PORTABLE_METADATA_IS_UNIT(m) (!IN_SET((m)->name[0], 0, '/'))
typedef enum PortableFlags {
PORTABLE_RUNTIME = 1 << 0,
PORTABLE_INSPECT_EXTENSION_RELEASES = 1 << 1, /* Public API via DBUS, do not change */
PORTABLE_PREFER_COPY = 1 << 2,
PORTABLE_PREFER_SYMLINK = 1 << 3,
PORTABLE_REATTACH = 1 << 4,
_PORTABLE_MASK_PUBLIC = PORTABLE_RUNTIME | PORTABLE_INSPECT_EXTENSION_RELEASES,
PORTABLE_RUNTIME = 1 << 0, /* Public API via DBUS, do not change */
PORTABLE_PREFER_COPY = 1 << 1,
PORTABLE_PREFER_SYMLINK = 1 << 2,
PORTABLE_REATTACH = 1 << 3,
_PORTABLE_MASK_PUBLIC = PORTABLE_RUNTIME,
_PORTABLE_TYPE_MAX,
_PORTABLE_TYPE_INVALID = -EINVAL,
_PORTABLE_TYPE_INVALID = -EINVAL,
} PortableFlags;
/* This enum is anonymous, since we usually store it in an 'int', as we overload it with negative errno
+77 -67
View File
@@ -260,7 +260,7 @@ static int maybe_reload(sd_bus **bus) {
static int get_image_metadata(sd_bus *bus, const char *image, char **matches, sd_bus_message **reply) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
PortableFlags flags = PORTABLE_INSPECT_EXTENSION_RELEASES;
uint64_t flags = 0;
const char *method;
int r;
@@ -362,71 +362,78 @@ static int inspect_image(int argc, char *argv[], void *userdata) {
strna(pretty_os));
}
r = sd_bus_message_enter_container(reply, 'a', "{say}");
if (r < 0)
return bus_log_parse_error(r);
if (!strv_isempty(arg_extension_images)) {
/* If we specified any extensions, we'll first get back exactly the paths (and
* extension-release content) for each one of the arguments. */
/* If we specified any extensions, we'll first get back exactly the
* paths (and extension-release content) for each one of the arguments. */
for (size_t i = 0; i < strv_length(arg_extension_images); ++i) {
const char *name;
r = sd_bus_message_enter_container(reply, 'e', "say");
if (r < 0)
return bus_log_parse_error(r);
if (r == 0)
break;
r = sd_bus_message_read(reply, "s", &name);
r = sd_bus_message_enter_container(reply, 'a', "{say}");
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_read_array(reply, 'y', &data, &sz);
if (r < 0)
return bus_log_parse_error(r);
for (size_t i = 0; i < strv_length(arg_extension_images); ++i) {
const char *name;
if (arg_cat) {
if (nl)
fputc('\n', stdout);
printf("%s-- Extension Release: %s --%s\n", ansi_highlight(), name, ansi_normal());
fwrite(data, sz, 1, stdout);
fflush(stdout);
nl = true;
} else {
_cleanup_free_ char *pretty_portable = NULL, *pretty_os = NULL, *sysext_level = NULL,
*id = NULL, *version_id = NULL, *sysext_scope = NULL, *portable_prefixes = NULL;
_cleanup_fclose_ FILE *f = NULL;
f = fmemopen_unlocked((void*) data, sz, "re");
if (!f)
return log_error_errno(errno, "Failed to open extension-release buffer: %m");
r = parse_env_file(f, name,
"ID", &id,
"VERSION_ID", &version_id,
"SYSEXT_SCOPE", &sysext_scope,
"SYSEXT_LEVEL", &sysext_level,
"PORTABLE_PRETTY_NAME", &pretty_portable,
"PORTABLE_PREFIXES", &portable_prefixes,
"PRETTY_NAME", &pretty_os);
r = sd_bus_message_enter_container(reply, 'e', "say");
if (r < 0)
return log_error_errno(r, "Failed to parse extension release from '%s': %m", name);
return bus_log_parse_error(r);
if (r == 0)
break;
printf("Extension:\n\t%s\n"
"\tExtension Scope:\n\t\t%s\n"
"\tExtension Compatibility Level:\n\t\t%s\n"
"\tPortable Service:\n\t\t%s\n"
"\tPortable Prefixes:\n\t\t%s\n"
"\tOperating System:\n\t\t%s (%s %s)\n",
name,
strna(sysext_scope),
strna(sysext_level),
strna(pretty_portable),
strna(portable_prefixes),
strna(pretty_os),
strna(id),
strna(version_id));
r = sd_bus_message_read(reply, "s", &name);
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_read_array(reply, 'y', &data, &sz);
if (r < 0)
return bus_log_parse_error(r);
if (arg_cat) {
if (nl)
fputc('\n', stdout);
printf("%s-- Extension Release: %s --%s\n", ansi_highlight(), name, ansi_normal());
fwrite(data, sz, 1, stdout);
fflush(stdout);
nl = true;
} else {
_cleanup_free_ char *pretty_portable = NULL, *pretty_os = NULL, *sysext_level = NULL,
*id = NULL, *version_id = NULL, *sysext_scope = NULL, *portable_prefixes = NULL;
_cleanup_fclose_ FILE *f = NULL;
f = fmemopen_unlocked((void*) data, sz, "re");
if (!f)
return log_error_errno(errno, "Failed to open extension-release buffer: %m");
r = parse_env_file(f, name,
"ID", &id,
"VERSION_ID", &version_id,
"SYSEXT_SCOPE", &sysext_scope,
"SYSEXT_LEVEL", &sysext_level,
"PORTABLE_PRETTY_NAME", &pretty_portable,
"PORTABLE_PREFIXES", &portable_prefixes,
"PRETTY_NAME", &pretty_os);
if (r < 0)
return log_error_errno(r, "Failed to parse extension release from '%s': %m", name);
printf("Extension:\n\t%s\n"
"\tExtension Scope:\n\t\t%s\n"
"\tExtension Compatibility Level:\n\t\t%s\n"
"\tPortable Service:\n\t\t%s\n"
"\tPortable Prefixes:\n\t\t%s\n"
"\tOperating System:\n\t\t%s (%s %s)\n",
name,
strna(sysext_scope),
strna(sysext_level),
strna(pretty_portable),
strna(portable_prefixes),
strna(pretty_os),
strna(id),
strna(version_id));
}
r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(reply);
@@ -434,6 +441,10 @@ static int inspect_image(int argc, char *argv[], void *userdata) {
return bus_log_parse_error(r);
}
r = sd_bus_message_enter_container(reply, 'a', "{say}");
if (r < 0)
return bus_log_parse_error(r);
for (;;) {
const char *name;
@@ -764,18 +775,17 @@ static int maybe_stop_disable(sd_bus *bus, char *image, char *argv[]) {
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_enter_container(reply, 'a', "{say}");
if (r < 0)
return bus_log_parse_error(r);
/* If we specified any extensions, we'll first get back exactly the
* paths (and extension-release content) for each one of the arguments. */
for (size_t i = 0; i < strv_length(arg_extension_images); ++i) {
r = sd_bus_message_skip(reply, "{say}");
/* If we specified any extensions, we'll first an array of extension-release metadata. */
if (!strv_isempty(arg_extension_images)) {
r = sd_bus_message_skip(reply, "a{say}");
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_enter_container(reply, 'a', "{say}");
if (r < 0)
return bus_log_parse_error(r);
for (;;) {
const char *name;
+1
View File
@@ -441,6 +441,7 @@ const sd_bus_vtable manager_vtable[] = {
"t", flags),
SD_BUS_RESULT("s", image,
"ay", os_release,
"a{say}", extensions,
"a{say}", units),
method_get_image_metadata,
SD_BUS_VTABLE_UNPRIVILEGED),
+19 -11
View File
@@ -108,7 +108,6 @@ int bus_image_common_get_metadata(
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ PortableMetadata **sorted = NULL;
PortableFlags flags = 0;
int r;
assert(name_or_path || image);
@@ -119,8 +118,10 @@ int bus_image_common_get_metadata(
m = image->userdata;
}
if (sd_bus_message_is_method_call(message, NULL, "GetImageMetadataWithExtensions") ||
sd_bus_message_is_method_call(message, NULL, "GetMetadataWithExtensions")) {
bool have_exti = sd_bus_message_is_method_call(message, NULL, "GetImageMetadataWithExtensions") ||
sd_bus_message_is_method_call(message, NULL, "GetMetadataWithExtensions");
if (have_exti) {
r = sd_bus_message_read_strv(message, &extension_images);
if (r < 0)
return r;
@@ -130,8 +131,7 @@ int bus_image_common_get_metadata(
if (r < 0)
return r;
if (sd_bus_message_is_method_call(message, NULL, "GetImageMetadataWithExtensions") ||
sd_bus_message_is_method_call(message, NULL, "GetMetadataWithExtensions")) {
if (have_exti) {
uint64_t input_flags = 0;
r = sd_bus_message_read(message, "t", &input_flags);
@@ -142,7 +142,6 @@ int bus_image_common_get_metadata(
return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS,
"Invalid 'flags' parameter '%" PRIu64 "'",
input_flags);
flags |= input_flags;
}
r = bus_image_acquire(m,
@@ -186,16 +185,16 @@ int bus_image_common_get_metadata(
if (r < 0)
return r;
r = sd_bus_message_open_container(reply, 'a', "{say}");
if (r < 0)
return r;
/* If it was requested, also send back the extension path and the content
* of each extension-release file. Behind a flag, as it's an incompatible
* change. */
if (FLAGS_SET(flags, PORTABLE_INSPECT_EXTENSION_RELEASES)) {
if (have_exti) {
PortableMetadata *extension_release;
r = sd_bus_message_open_container(reply, 'a', "{say}");
if (r < 0)
return r;
ORDERED_HASHMAP_FOREACH(extension_release, extension_releases) {
r = sd_bus_message_open_container(reply, 'e', "say");
@@ -214,8 +213,16 @@ int bus_image_common_get_metadata(
if (r < 0)
return r;
}
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
}
r = sd_bus_message_open_container(reply, 'a', "{say}");
if (r < 0)
return r;
for (size_t i = 0; i < hashmap_size(unit_files); i++) {
r = sd_bus_message_open_container(reply, 'e', "say");
@@ -888,6 +895,7 @@ const sd_bus_vtable image_vtable[] = {
"t", flags),
SD_BUS_RESULT("s", image,
"ay", os_release,
"a{say}", extensions,
"a{say}", units),
bus_image_method_get_metadata,
SD_BUS_VTABLE_UNPRIVILEGED),