Image *image,
sd_bus_error *error) {
+ _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_releases = NULL;
_cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
_cleanup_strv_free_ char **matches = NULL, **extension_images = NULL;
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ PortableMetadata **sorted = NULL;
- /* Unused for now, but added to the DBUS methods for future-proofing */
- uint64_t input_flags = 0;
- size_t i;
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);
if (r < 0)
return r;
- /* Let clients know that this version doesn't support any flags */
- if (input_flags != 0)
+
+ if ((input_flags & ~_PORTABLE_MASK_PUBLIC) != 0)
return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS,
"Invalid 'flags' parameter '%" PRIu64 "'",
input_flags);
matches,
extension_images,
&os_release,
+ &extension_releases,
&unit_files,
+ NULL,
error);
if (r < 0)
return r;
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 (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_append(reply, "s", extension_release->image_path);
+ if (r < 0)
+ return r;
+
+ r = append_fd(reply, extension_release);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_close_container(reply);
+ 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 (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");
if (r < 0)
void *userdata,
sd_bus_error *error) {
- Image *image = userdata;
+ _cleanup_strv_free_ char **extension_images = NULL;
+ Image *image = ASSERT_PTR(userdata);
PortableState state;
int r;
assert(message);
- assert(image);
+
+ if (sd_bus_message_is_method_call(message, NULL, "GetStateWithExtensions")) {
+ uint64_t input_flags = 0;
+
+ r = sd_bus_message_read_strv(message, &extension_images);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(message, "t", &input_flags);
+ if (r < 0)
+ return r;
+
+ /* No flags are supported by this method for now. */
+ if (input_flags != 0)
+ return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid 'flags' parameter '%" PRIu64 "'",
+ input_flags);
+ }
r = portable_get_state(
sd_bus_message_get_bus(message),
image->path,
+ extension_images,
0,
&state,
error);
_cleanup_strv_free_ char **extension_images = NULL;
PortableChange *changes = NULL;
- Image *image = userdata;
- Manager *m = image->userdata;
+ Image *image = ASSERT_PTR(userdata);
+ Manager *m = ASSERT_PTR(image->userdata);
PortableFlags flags = 0;
size_t n_changes = 0;
int r;
assert(message);
- assert(image);
- assert(m);
if (sd_bus_message_is_method_call(message, NULL, "DetachWithExtensions")) {
r = sd_bus_message_read_strv(message, &extension_images);
r = portable_get_state(
sd_bus_message_get_bus(message),
image->path,
+ NULL,
0,
&state,
error);
"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),
SD_BUS_RESULT("s", state),
bus_image_method_get_state,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetStateWithExtensions",
+ SD_BUS_ARGS("as", extensions,
+ "t", flags),
+ SD_BUS_RESULT("s", state),
+ bus_image_method_get_state,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("Attach",
SD_BUS_ARGS("as", matches,
"s", profile,
/* If it's a short name, let's search for it */
r = image_find(IMAGE_PORTABLE, name_or_path, NULL, &loaded);
if (r == -ENOENT)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PORTABLE_IMAGE, "No image '%s' found.", name_or_path);
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PORTABLE_IMAGE,
+ "No image '%s' found.", name_or_path);
/* other errors are handled below… */
} else {
/* Don't accept path if this is always forbidden */
if (mode == BUS_IMAGE_REFUSE_BY_PATH)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Expected image name, not path in place of '%s'.", name_or_path);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Expected image name, not path in place of '%s'.", name_or_path);
if (!path_is_absolute(name_or_path))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is not valid or not a valid path.", name_or_path);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Image name '%s' is not valid or not a valid path.", name_or_path);
if (!path_is_normalized(name_or_path))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image path '%s' is not normalized.", name_or_path);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Image path '%s' is not normalized.", name_or_path);
if (mode == BUS_IMAGE_AUTHENTICATE_BY_PATH) {
r = bus_verify_polkit_async(
r = image_from_path(name_or_path, &loaded);
}
if (r == -EMEDIUMTYPE) {
- sd_bus_error_setf(error, BUS_ERROR_BAD_PORTABLE_IMAGE_TYPE, "Typ of image '%s' not recognized; supported image types are directories/btrfs subvolumes, block devices, and raw disk image files with suffix '.raw'.", name_or_path);
+ sd_bus_error_setf(error, BUS_ERROR_BAD_PORTABLE_IMAGE_TYPE,
+ "Type of image '%s' not recognized; supported image types are directories/btrfs subvolumes, block devices, and raw disk image files with suffix '.raw'.",
+ name_or_path);
return r;
}
if (r < 0)
return 0;
if (r == 0)
goto not_found;
+ if (isempty(e))
+ /* The path is "/org/freedesktop/portable1/image" itself */
+ goto not_found;
r = bus_image_acquire(m, sd_bus_get_current_message(bus), e, NULL, BUS_IMAGE_REFUSE_BY_PATH, NULL, &image, error);
if (r == -ENOENT)
int bus_image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
_cleanup_hashmap_free_ Hashmap *images = NULL;
_cleanup_strv_free_ char **l = NULL;
- size_t n_allocated = 0, n = 0;
Manager *m = userdata;
+ size_t n = 0;
Image *image;
int r;
if (r < 0)
return r;
- if (!GREEDY_REALLOC(l, n_allocated, n+2)) {
+ if (!GREEDY_REALLOC(l, n+2)) {
free(p);
return -ENOMEM;
}