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 const sd_bus_vtable image_vtable[] = {
186 SD_BUS_VTABLE_START(0),
187 SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0),
188 SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0),
189 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0),
190 SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0),
191 SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0),
192 SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0),
193 SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0),
194 SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0),
195 SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0),
196 SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0),
197 SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
198 SD_BUS_METHOD("Rename", "s", NULL, bus_image_method_rename, SD_BUS_VTABLE_UNPRIVILEGED),
199 SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED),
200 SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
204 static int image_flush_cache(sd_event_source *s, void *userdata) {
205 Manager *m = userdata;
211 while ((i = hashmap_steal_first(m->image_cache)))
217 int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
218 _cleanup_free_ char *e = NULL;
219 Manager *m = userdata;
229 p = startswith(path, "/org/freedesktop/machine1/image/");
233 e = bus_label_unescape(p);
237 image = hashmap_get(m->image_cache, e);
243 r = hashmap_ensure_allocated(&m->image_cache, &string_hash_ops);
247 if (!m->image_cache_defer_event) {
248 r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_flush_cache, m);
252 r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE);
257 r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT);
261 r = image_find(e, &image);
267 r = hashmap_put(m->image_cache, image->name, image);
277 char *image_bus_path(const char *name) {
278 _cleanup_free_ char *e = NULL;
282 e = bus_label_escape(name);
286 return strappend("/org/freedesktop/machine1/image/", e);
289 int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
290 _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
291 _cleanup_strv_free_ char **l = NULL;
300 images = hashmap_new(&string_hash_ops);
304 r = image_discover(images);
308 HASHMAP_FOREACH(image, images, i) {
311 p = image_bus_path(image->name);
315 r = strv_consume(&l, p);