mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-10-26 08:55:18 +03:00
portable: add return parameter to GetImageMetadataWithExtensions
The complaint was that the output array was used for two kinds of data, and the
input flag decided whether this extra data should be included. The flag is
removed, and instead the old method is changed to include the data always as
a separate parameter.
This breaks backward compatibility, but the old method is effectively broken
and does not appear to be used yet, at least in open source code, by
searching on codesearch.debian.net and github.com.
Fixes #22404.
Co-authored-by: Luca Boccassi <bluca@debian.org>
(cherry picked from commit 087a799f64
)
This commit is contained in:
parent
06d466a05c
commit
00b5aa8d74
@ -54,6 +54,7 @@ node /org/freedesktop/portable1 {
|
|||||||
in t flags,
|
in t flags,
|
||||||
out s image,
|
out s image,
|
||||||
out ay os_release,
|
out ay os_release,
|
||||||
|
out a{say} extensions,
|
||||||
out a{say} units);
|
out a{say} units);
|
||||||
GetImageState(in s image,
|
GetImageState(in s image,
|
||||||
out s state);
|
out s state);
|
||||||
@ -183,19 +184,12 @@ node /org/freedesktop/portable1 {
|
|||||||
and a list of portable units contained in the image, in the form of a string (unit name) and
|
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>
|
an array of bytes with the content.</para>
|
||||||
|
|
||||||
<para><function>GetImageMetadataWithExtensions()</function> retrieves metadata associated with an image.
|
<para><function>GetImageMetadataWithExtensions()</function> retrieves metadata associated with an
|
||||||
This method is a superset of <function>GetImageMetadata()</function> with the addition of
|
image. This method is a superset of <function>GetImageMetadata()</function> with the addition of a list
|
||||||
a list of extensions as input parameter, which were overlaid on top of the main
|
of extensions as input parameter, which were overlaid on top of the main image via
|
||||||
image via <function>AttachImageWithExtensions()</function>.
|
<function>AttachImageWithExtensions()</function>. The path of each extension and an array of bytes with
|
||||||
The <varname>flag</varname> parameter can be used to request that, before the units, the path of
|
the content of the respective extension-release file are returned, one such structure for each
|
||||||
each extension and an array of bytes with the content of the respective extension-release file
|
extension named in the input arguments.</para>
|
||||||
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>GetImageState()</function> retrieves the image state as one of the following
|
<para><function>GetImageState()</function> retrieves the image state as one of the following
|
||||||
strings:
|
strings:
|
||||||
@ -340,6 +334,7 @@ node /org/freedesktop/portable1 {
|
|||||||
in t flags,
|
in t flags,
|
||||||
out s image,
|
out s image,
|
||||||
out ay os_release,
|
out ay os_release,
|
||||||
|
out a{say} extensions,
|
||||||
out a{say} units);
|
out a{say} units);
|
||||||
GetState(out s state);
|
GetState(out s state);
|
||||||
Attach(in as matches,
|
Attach(in as matches,
|
||||||
|
@ -21,14 +21,13 @@ typedef struct PortableMetadata {
|
|||||||
#define PORTABLE_METADATA_IS_UNIT(m) (!IN_SET((m)->name[0], 0, '/'))
|
#define PORTABLE_METADATA_IS_UNIT(m) (!IN_SET((m)->name[0], 0, '/'))
|
||||||
|
|
||||||
typedef enum PortableFlags {
|
typedef enum PortableFlags {
|
||||||
PORTABLE_RUNTIME = 1 << 0,
|
PORTABLE_RUNTIME = 1 << 0, /* Public API via DBUS, do not change */
|
||||||
PORTABLE_INSPECT_EXTENSION_RELEASES = 1 << 1, /* Public API via DBUS, do not change */
|
PORTABLE_PREFER_COPY = 1 << 1,
|
||||||
PORTABLE_PREFER_COPY = 1 << 2,
|
PORTABLE_PREFER_SYMLINK = 1 << 2,
|
||||||
PORTABLE_PREFER_SYMLINK = 1 << 3,
|
PORTABLE_REATTACH = 1 << 3,
|
||||||
PORTABLE_REATTACH = 1 << 4,
|
_PORTABLE_MASK_PUBLIC = PORTABLE_RUNTIME,
|
||||||
_PORTABLE_MASK_PUBLIC = PORTABLE_RUNTIME | PORTABLE_INSPECT_EXTENSION_RELEASES,
|
|
||||||
_PORTABLE_TYPE_MAX,
|
_PORTABLE_TYPE_MAX,
|
||||||
_PORTABLE_TYPE_INVALID = -EINVAL,
|
_PORTABLE_TYPE_INVALID = -EINVAL,
|
||||||
} PortableFlags;
|
} PortableFlags;
|
||||||
|
|
||||||
/* This enum is anonymous, since we usually store it in an 'int', as we overload it with negative errno
|
/* This enum is anonymous, since we usually store it in an 'int', as we overload it with negative errno
|
||||||
|
@ -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) {
|
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_message_unrefp) sd_bus_message *m = NULL;
|
||||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_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;
|
const char *method;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -362,71 +362,78 @@ static int inspect_image(int argc, char *argv[], void *userdata) {
|
|||||||
strna(pretty_os));
|
strna(pretty_os));
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_bus_message_enter_container(reply, 'a', "{say}");
|
if (!strv_isempty(arg_extension_images)) {
|
||||||
if (r < 0)
|
/* If we specified any extensions, we'll first get back exactly the paths (and
|
||||||
return bus_log_parse_error(r);
|
* extension-release content) for each one of the arguments. */
|
||||||
|
|
||||||
/* If we specified any extensions, we'll first get back exactly the
|
r = sd_bus_message_enter_container(reply, 'a', "{say}");
|
||||||
* 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);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return bus_log_parse_error(r);
|
return bus_log_parse_error(r);
|
||||||
|
|
||||||
r = sd_bus_message_read_array(reply, 'y', &data, &sz);
|
for (size_t i = 0; i < strv_length(arg_extension_images); ++i) {
|
||||||
if (r < 0)
|
const char *name;
|
||||||
return bus_log_parse_error(r);
|
|
||||||
|
|
||||||
if (arg_cat) {
|
r = sd_bus_message_enter_container(reply, 'e', "say");
|
||||||
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)
|
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"
|
r = sd_bus_message_read(reply, "s", &name);
|
||||||
"\tExtension Scope:\n\t\t%s\n"
|
if (r < 0)
|
||||||
"\tExtension Compatibility Level:\n\t\t%s\n"
|
return bus_log_parse_error(r);
|
||||||
"\tPortable Service:\n\t\t%s\n"
|
|
||||||
"\tPortable Prefixes:\n\t\t%s\n"
|
r = sd_bus_message_read_array(reply, 'y', &data, &sz);
|
||||||
"\tOperating System:\n\t\t%s (%s %s)\n",
|
if (r < 0)
|
||||||
name,
|
return bus_log_parse_error(r);
|
||||||
strna(sysext_scope),
|
|
||||||
strna(sysext_level),
|
if (arg_cat) {
|
||||||
strna(pretty_portable),
|
if (nl)
|
||||||
strna(portable_prefixes),
|
fputc('\n', stdout);
|
||||||
strna(pretty_os),
|
|
||||||
strna(id),
|
printf("%s-- Extension Release: %s --%s\n", ansi_highlight(), name, ansi_normal());
|
||||||
strna(version_id));
|
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);
|
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);
|
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 (;;) {
|
for (;;) {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
@ -764,18 +775,17 @@ static int maybe_stop_disable(sd_bus *bus, char *image, char *argv[]) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return bus_log_parse_error(r);
|
return bus_log_parse_error(r);
|
||||||
|
|
||||||
r = sd_bus_message_enter_container(reply, 'a', "{say}");
|
/* If we specified any extensions, we'll first an array of extension-release metadata. */
|
||||||
if (r < 0)
|
if (!strv_isempty(arg_extension_images)) {
|
||||||
return bus_log_parse_error(r);
|
r = sd_bus_message_skip(reply, "a{say}");
|
||||||
|
|
||||||
/* 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 (r < 0)
|
if (r < 0)
|
||||||
return bus_log_parse_error(r);
|
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 (;;) {
|
for (;;) {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
|
@ -420,6 +420,7 @@ const sd_bus_vtable manager_vtable[] = {
|
|||||||
"t", flags),
|
"t", flags),
|
||||||
SD_BUS_RESULT("s", image,
|
SD_BUS_RESULT("s", image,
|
||||||
"ay", os_release,
|
"ay", os_release,
|
||||||
|
"a{say}", extensions,
|
||||||
"a{say}", units),
|
"a{say}", units),
|
||||||
method_get_image_metadata,
|
method_get_image_metadata,
|
||||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
@ -108,7 +108,6 @@ int bus_image_common_get_metadata(
|
|||||||
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
|
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
|
||||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||||
_cleanup_free_ PortableMetadata **sorted = NULL;
|
_cleanup_free_ PortableMetadata **sorted = NULL;
|
||||||
PortableFlags flags = 0;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(name_or_path || image);
|
assert(name_or_path || image);
|
||||||
@ -119,8 +118,10 @@ int bus_image_common_get_metadata(
|
|||||||
m = image->userdata;
|
m = image->userdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sd_bus_message_is_method_call(message, NULL, "GetImageMetadataWithExtensions") ||
|
bool have_exti = sd_bus_message_is_method_call(message, NULL, "GetImageMetadataWithExtensions") ||
|
||||||
sd_bus_message_is_method_call(message, NULL, "GetMetadataWithExtensions")) {
|
sd_bus_message_is_method_call(message, NULL, "GetMetadataWithExtensions");
|
||||||
|
|
||||||
|
if (have_exti) {
|
||||||
r = sd_bus_message_read_strv(message, &extension_images);
|
r = sd_bus_message_read_strv(message, &extension_images);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -130,8 +131,7 @@ int bus_image_common_get_metadata(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (sd_bus_message_is_method_call(message, NULL, "GetImageMetadataWithExtensions") ||
|
if (have_exti) {
|
||||||
sd_bus_message_is_method_call(message, NULL, "GetMetadataWithExtensions")) {
|
|
||||||
uint64_t input_flags = 0;
|
uint64_t input_flags = 0;
|
||||||
|
|
||||||
r = sd_bus_message_read(message, "t", &input_flags);
|
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,
|
return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS,
|
||||||
"Invalid 'flags' parameter '%" PRIu64 "'",
|
"Invalid 'flags' parameter '%" PRIu64 "'",
|
||||||
input_flags);
|
input_flags);
|
||||||
flags |= input_flags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = bus_image_acquire(m,
|
r = bus_image_acquire(m,
|
||||||
@ -186,16 +185,16 @@ int bus_image_common_get_metadata(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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
|
/* 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
|
* of each extension-release file. Behind a flag, as it's an incompatible
|
||||||
* change. */
|
* change. */
|
||||||
if (FLAGS_SET(flags, PORTABLE_INSPECT_EXTENSION_RELEASES)) {
|
if (have_exti) {
|
||||||
PortableMetadata *extension_release;
|
PortableMetadata *extension_release;
|
||||||
|
|
||||||
|
r = sd_bus_message_open_container(reply, 'a', "{say}");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
ORDERED_HASHMAP_FOREACH(extension_release, extension_releases) {
|
ORDERED_HASHMAP_FOREACH(extension_release, extension_releases) {
|
||||||
|
|
||||||
r = sd_bus_message_open_container(reply, 'e', "say");
|
r = sd_bus_message_open_container(reply, 'e', "say");
|
||||||
@ -214,8 +213,16 @@ int bus_image_common_get_metadata(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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++) {
|
for (size_t i = 0; i < hashmap_size(unit_files); i++) {
|
||||||
|
|
||||||
r = sd_bus_message_open_container(reply, 'e', "say");
|
r = sd_bus_message_open_container(reply, 'e', "say");
|
||||||
@ -867,6 +874,7 @@ const sd_bus_vtable image_vtable[] = {
|
|||||||
"t", flags),
|
"t", flags),
|
||||||
SD_BUS_RESULT("s", image,
|
SD_BUS_RESULT("s", image,
|
||||||
"ay", os_release,
|
"ay", os_release,
|
||||||
|
"a{say}", extensions,
|
||||||
"a{say}", units),
|
"a{say}", units),
|
||||||
bus_image_method_get_metadata,
|
bus_image_method_get_metadata,
|
||||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
Loading…
Reference in New Issue
Block a user