1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "bus-label.h"
25 #include "machine-image.h"
26 #include "image-dbus.h"
28 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, image_type, ImageType);
30 int bus_image_method_remove(
32 sd_bus_message *message,
34 sd_bus_error *error) {
36 Image *image = userdata;
37 Manager *m = image->userdata;
44 r = bus_verify_polkit_async(
47 "org.freedesktop.machine1.manage-images",
55 return 1; /* Will call us back */
57 r = image_remove(image);
61 return sd_bus_reply_method_return(message, NULL);
64 int bus_image_method_rename(
66 sd_bus_message *message,
68 sd_bus_error *error) {
70 Image *image = userdata;
71 Manager *m = image->userdata;
79 r = sd_bus_message_read(message, "s", &new_name);
83 if (!image_name_is_valid(new_name))
84 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
86 r = bus_verify_polkit_async(
89 "org.freedesktop.machine1.manage-images",
97 return 1; /* Will call us back */
99 r = image_rename(image, new_name);
103 return sd_bus_reply_method_return(message, NULL);
106 int bus_image_method_clone(
108 sd_bus_message *message,
110 sd_bus_error *error) {
112 Image *image = userdata;
113 Manager *m = image->userdata;
114 const char *new_name;
121 r = sd_bus_message_read(message, "sb", &new_name, &read_only);
125 if (!image_name_is_valid(new_name))
126 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
128 r = bus_verify_polkit_async(
131 "org.freedesktop.machine1.manage-images",
139 return 1; /* Will call us back */
141 r = image_clone(image, new_name, read_only);
145 return sd_bus_reply_method_return(message, NULL);
148 int bus_image_method_mark_read_only(
150 sd_bus_message *message,
152 sd_bus_error *error) {
154 Image *image = userdata;
155 Manager *m = image->userdata;
161 r = sd_bus_message_read(message, "b", &read_only);
165 r = bus_verify_polkit_async(
168 "org.freedesktop.machine1.manage-images",
176 return 1; /* Will call us back */
178 r = image_read_only(image, read_only);
182 return sd_bus_reply_method_return(message, NULL);
185 int bus_image_method_set_limit(
187 sd_bus_message *message,
189 sd_bus_error *error) {
191 Image *image = userdata;
192 Manager *m = image->userdata;
199 r = sd_bus_message_read(message, "t", &limit);
203 r = bus_verify_polkit_async(
206 "org.freedesktop.machine1.manage-images",
214 return 1; /* Will call us back */
216 r = image_set_limit(image, limit);
220 return sd_bus_reply_method_return(message, NULL);
223 const sd_bus_vtable image_vtable[] = {
224 SD_BUS_VTABLE_START(0),
225 SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0),
226 SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0),
227 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0),
228 SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0),
229 SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0),
230 SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0),
231 SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0),
232 SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0),
233 SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0),
234 SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0),
235 SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
236 SD_BUS_METHOD("Rename", "s", NULL, bus_image_method_rename, SD_BUS_VTABLE_UNPRIVILEGED),
237 SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED),
238 SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
239 SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED),
243 static int image_flush_cache(sd_event_source *s, void *userdata) {
244 Manager *m = userdata;
250 while ((i = hashmap_steal_first(m->image_cache)))
256 int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
257 _cleanup_free_ char *e = NULL;
258 Manager *m = userdata;
268 p = startswith(path, "/org/freedesktop/machine1/image/");
272 e = bus_label_unescape(p);
276 image = hashmap_get(m->image_cache, e);
282 r = hashmap_ensure_allocated(&m->image_cache, &string_hash_ops);
286 if (!m->image_cache_defer_event) {
287 r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_flush_cache, m);
291 r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE);
296 r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT);
300 r = image_find(e, &image);
306 r = hashmap_put(m->image_cache, image->name, image);
316 char *image_bus_path(const char *name) {
317 _cleanup_free_ char *e = NULL;
321 e = bus_label_escape(name);
325 return strappend("/org/freedesktop/machine1/image/", e);
328 int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
329 _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
330 _cleanup_strv_free_ char **l = NULL;
339 images = hashmap_new(&string_hash_ops);
343 r = image_discover(images);
347 HASHMAP_FOREACH(image, images, i) {
350 p = image_bus_path(image->name);
354 r = strv_consume(&l, p);