in t flags,
out s image,
out ay os_release,
+ out a{say} extensions,
out a{say} units);
GetImageState(in s image,
out s state);
and a list of portable units contained in the image, in the form of a string (unit name) and
an array of bytes with the content.</para>
- <para><function>GetImageMetadataWithExtensions()</function> retrieves metadata associated with an image.
- This method is a superset of <function>GetImageMetadata()</function> with the addition of
- a list of extensions as input parameter, which were overlaid on top of the main
- image via <function>AttachImageWithExtensions()</function>.
- The <varname>flag</varname> parameter can be used to request that, before the units, the path of
- each extension and an array of bytes with the content of the respective extension-release file
- are sent. One such structure will be sent for each extension named in the input arguments. The
- flag value to enable this functionality is defined as follows:</para>
-
- <programlisting>
-#define PORTABLE_INSPECT_EXTENSION_RELEASES (UINT64_C(1) << 1)
- </programlisting>
-
+ <para><function>GetImageMetadataWithExtensions()</function> retrieves metadata associated with an
+ image. This method is a superset of <function>GetImageMetadata()</function> with the addition of a list
+ of extensions as input parameter, which were overlaid on top of the main image via
+ <function>AttachImageWithExtensions()</function>. The path of each extension and an array of bytes with
+ the content of the respective extension-release file are returned, one such structure for each
+ extension named in the input arguments.</para>
<para><function>GetImageState()</function> retrieves the image state as one of the following
strings:
in t flags,
out s image,
out ay os_release,
+ out a{say} extensions,
out a{say} units);
GetState(out s state);
GetStateWithExtensions(in as extensions,
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;
strna(pretty_os));
}
- 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) {
- const char *name;
+ 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. */
- r = sd_bus_message_enter_container(reply, 'e', "say");
+ r = sd_bus_message_enter_container(reply, 'a', "{say}");
if (r < 0)
return bus_log_parse_error(r);
- if (r == 0)
- break;
- r = sd_bus_message_read(reply, "s", &name);
- if (r < 0)
- return bus_log_parse_error(r);
+ for (size_t i = 0; i < strv_length(arg_extension_images); ++i) {
+ const char *name;
- r = sd_bus_message_read_array(reply, 'y', &data, &sz);
- if (r < 0)
- return bus_log_parse_error(r);
+ r = sd_bus_message_enter_container(reply, 'e', "say");
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
- if (arg_cat) {
- if (nl)
- fputc('\n', stdout);
+ r = sd_bus_message_read(reply, "s", &name);
+ if (r < 0)
+ return bus_log_parse_error(r);
- 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_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 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));
+ return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(reply);
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;
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;
_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);
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;
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);
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,
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");
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");
"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),