#include "alloc-util.h"
#include "btrfs-util.h"
#include "bus-common-errors.h"
+#include "bus-object.h"
#include "bus-polkit.h"
#include "discover-image.h"
#include "fd-util.h"
void *userdata,
sd_bus_error *error) {
- _cleanup_close_ int fd = -1;
- uint64_t usage = (uint64_t) -1;
+ _cleanup_close_ int fd = -EBADF;
+ uint64_t usage = UINT64_MAX;
assert(bus);
assert(reply);
void *userdata,
sd_bus_error *error) {
- _cleanup_close_ int fd = -1;
- uint64_t size = (uint64_t) -1;
+ _cleanup_close_ int fd = -EBADF;
+ uint64_t size = UINT64_MAX;
assert(bus);
assert(reply);
static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
- Manager *m = userdata;
+ Manager *m = ASSERT_PTR(userdata);
const char *name;
Image *image;
int r;
assert(message);
- assert(m);
r = sd_bus_message_read(message, "s", &name);
if (r < 0)
static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_hashmap_free_ Hashmap *images = NULL;
- Manager *m = userdata;
+ Manager *m = ASSERT_PTR(userdata);
Image *image;
int r;
assert(message);
- assert(m);
images = hashmap_new(&image_hash_ops);
if (!images)
r = portable_get_state(
sd_bus_message_get_bus(message),
image->path,
+ NULL,
0,
&state,
&error_state);
}
static int method_get_image_state(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_strv_free_ char **extension_images = NULL;
const char *name_or_path;
PortableState state;
int r;
if (r < 0)
return r;
+ if (sd_bus_message_is_method_call(message, NULL, "GetImageStateWithExtensions")) {
+ 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),
name_or_path,
+ extension_images,
0,
&state,
error);
}
static int method_detach_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_strv_free_ char **extension_images = NULL;
PortableChange *changes = NULL;
- Manager *m = userdata;
+ PortableFlags flags = 0;
+ Manager *m = ASSERT_PTR(userdata);
size_t n_changes = 0;
const char *name_or_path;
- int r, runtime;
+ int r;
assert(message);
- assert(m);
+
+ CLEANUP_ARRAY(changes, n_changes, portable_changes_free);
/* Note that we do not redirect detaching to the image object here, because we want to allow that users can
* detach already deleted images too, in case the user already deleted an image before properly detaching
* it. */
- r = sd_bus_message_read(message, "sb", &name_or_path, &runtime);
+ r = sd_bus_message_read(message, "s", &name_or_path);
if (r < 0)
return r;
+ if (sd_bus_message_is_method_call(message, NULL, "DetachImageWithExtensions")) {
+ 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;
+
+ 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);
+ flags |= input_flags;
+ } else {
+ int runtime;
+
+ r = sd_bus_message_read(message, "b", &runtime);
+ if (r < 0)
+ return r;
+
+ if (runtime)
+ flags |= PORTABLE_RUNTIME;
+ }
+
r = bus_verify_polkit_async(
message,
- CAP_SYS_ADMIN,
"org.freedesktop.portable1.attach-images",
- NULL,
- false,
- UID_INVALID,
+ /* details= */ NULL,
&m->polkit_registry,
error);
if (r < 0)
r = portable_detach(
sd_bus_message_get_bus(message),
name_or_path,
- runtime ? PORTABLE_RUNTIME : 0,
+ extension_images,
+ flags,
&changes,
&n_changes,
error);
if (r < 0)
- goto finish;
-
- r = reply_portable_changes(message, changes, n_changes);
+ return r;
-finish:
- portable_changes_free(changes, n_changes);
- return r;
+ return reply_portable_changes(message, changes, n_changes);
}
static int method_reattach_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
if (r < 0)
return r;
if (!FILE_SIZE_VALID_OR_INFINITY(limit))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
+ return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
r = bus_verify_polkit_async(
message,
- CAP_SYS_ADMIN,
"org.freedesktop.portable1.manage-images",
- NULL,
- false,
- UID_INVALID,
+ /* details= */ NULL,
&m->polkit_registry,
error);
if (r < 0)
r = btrfs_subvol_set_subtree_quota_limit("/var/lib/portables", 0, limit);
if (r == -ENOTTY)
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
+ return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m");
SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
SD_BUS_PROPERTY("Profiles", "as", property_get_profiles, 0, 0),
- SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ListImages", NULL, "a(ssbtttso)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetImageOSRelease", "s", "a{ss}", method_get_image_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetImageMetadata", "sas", "saya{say}", method_get_image_metadata, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetImageState", "s", "s", method_get_image_state, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("AttachImage", "sassbs", "a(sss)", method_attach_image, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("DetachImage", "sb", "a(sss)", method_detach_image, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ReattachImage", "sassbs", "a(sss)a(sss)", method_reattach_image, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetImage",
+ SD_BUS_ARGS("s", image),
+ SD_BUS_RESULT("o", object),
+ method_get_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("ListImages",
+ SD_BUS_NO_ARGS,
+ SD_BUS_RESULT("a(ssbtttso)", images),
+ method_list_images,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetImageOSRelease",
+ SD_BUS_ARGS("s", image),
+ SD_BUS_RESULT("a{ss}", os_release),
+ method_get_image_os_release,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetImageMetadata",
+ SD_BUS_ARGS("s", image,
+ "as", matches),
+ SD_BUS_RESULT("s", image,
+ "ay", os_release,
+ "a{say}", units),
+ method_get_image_metadata,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetImageMetadataWithExtensions",
+ SD_BUS_ARGS("s", image,
+ "as", extensions,
+ "as", matches,
+ "t", flags),
+ SD_BUS_RESULT("s", image,
+ "ay", os_release,
+ "a{say}", extensions,
+ "a{say}", units),
+ method_get_image_metadata,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetImageState",
+ SD_BUS_ARGS("s", image),
+ SD_BUS_RESULT("s", state),
+ method_get_image_state,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetImageStateWithExtensions",
+ SD_BUS_ARGS("s", image,
+ "as", extensions,
+ "t", flags),
+ SD_BUS_RESULT("s", state),
+ method_get_image_state,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("AttachImage",
+ SD_BUS_ARGS("s", image,
+ "as", matches,
+ "s", profile,
+ "b", runtime,
+ "s", copy_mode),
+ SD_BUS_RESULT("a(sss)", changes),
+ method_attach_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("AttachImageWithExtensions",
+ SD_BUS_ARGS("s", image,
+ "as", extensions,
+ "as", matches,
+ "s", profile,
+ "s", copy_mode,
+ "t", flags),
+ SD_BUS_RESULT("a(sss)", changes),
+ method_attach_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("DetachImage",
+ SD_BUS_ARGS("s", image,
+ "b", runtime),
+ SD_BUS_RESULT("a(sss)", changes),
+ method_detach_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("DetachImageWithExtensions",
+ SD_BUS_ARGS("s", image,
+ "as", extensions,
+ "t", flags),
+ SD_BUS_RESULT("a(sss)", changes),
+ method_detach_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("ReattachImage",
+ SD_BUS_ARGS("s", image,
+ "as", matches,
+ "s", profile,
+ "b", runtime,
+ "s", copy_mode),
+ SD_BUS_RESULT("a(sss)", changes_removed,
+ "a(sss)", changes_updated),
+ method_reattach_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("ReattachImageWithExtensions",
+ SD_BUS_ARGS("s", image,
+ "as", extensions,
+ "as", matches,
+ "s", profile,
+ "s", copy_mode,
+ "t", flags),
+ SD_BUS_RESULT("a(sss)", changes_removed,
+ "a(sss)", changes_updated),
+ method_reattach_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("RemoveImage",
+ SD_BUS_ARGS("s", image),
+ SD_BUS_NO_RESULT,
+ method_remove_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("MarkImageReadOnly",
+ SD_BUS_ARGS("s", image,
+ "b", read_only),
+ SD_BUS_NO_RESULT,
+ method_mark_image_read_only,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetImageLimit",
+ SD_BUS_ARGS("s", image,
+ "t", limit),
+ SD_BUS_NO_RESULT,
+ method_set_image_limit,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetPoolLimit",
+ SD_BUS_ARGS("t", limit),
+ SD_BUS_NO_RESULT,
+ method_set_pool_limit,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};
+const BusObjectImplementation manager_object = {
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ .vtables = BUS_VTABLES(manager_vtable),
+ .children = BUS_IMPLEMENTATIONS(&image_object),
+};
+
static int reply_portable_compose_message(sd_bus_message *reply, const PortableChange *changes, size_t n_changes) {
size_t i;
int r;
return r;
for (i = 0; i < n_changes; i++) {
+ if (changes[i].type_or_errno < 0)
+ continue;
+
r = sd_bus_message_append(reply, "(sss)",
- portable_change_type_to_string(changes[i].type),
+ portable_change_type_to_string(changes[i].type_or_errno),
changes[i].path,
changes[i].source);
if (r < 0)