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"
23 #include "bus-common-errors.h"
26 #include "machine-image.h"
27 #include "image-dbus.h"
29 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, image_type, ImageType);
31 int bus_image_method_remove(
33 sd_bus_message *message,
35 sd_bus_error *error) {
37 Image *image = userdata;
38 Manager *m = image->userdata;
45 r = bus_verify_polkit_async(
48 "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",
96 return 1; /* Will call us back */
98 r = image_rename(image, new_name);
102 return sd_bus_reply_method_return(message, NULL);
105 int bus_image_method_clone(
107 sd_bus_message *message,
109 sd_bus_error *error) {
111 Image *image = userdata;
112 Manager *m = image->userdata;
113 const char *new_name;
120 r = sd_bus_message_read(message, "sb", &new_name, &read_only);
124 if (!image_name_is_valid(new_name))
125 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
127 r = bus_verify_polkit_async(
130 "org.freedesktop.machine1.manage-images",
137 return 1; /* Will call us back */
139 r = image_clone(image, new_name, read_only);
143 return sd_bus_reply_method_return(message, NULL);
146 int bus_image_method_mark_read_only(
148 sd_bus_message *message,
150 sd_bus_error *error) {
152 Image *image = userdata;
153 Manager *m = image->userdata;
159 r = sd_bus_message_read(message, "b", &read_only);
163 r = bus_verify_polkit_async(
166 "org.freedesktop.machine1.manage-images",
173 return 1; /* Will call us back */
175 r = image_read_only(image, read_only);
179 return sd_bus_reply_method_return(message, NULL);
182 const sd_bus_vtable image_vtable[] = {
183 SD_BUS_VTABLE_START(0),
184 SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0),
185 SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0),
186 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0),
187 SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0),
188 SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0),
189 SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0),
190 SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0),
191 SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0),
192 SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0),
193 SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0),
194 SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
195 SD_BUS_METHOD("Rename", "s", NULL, bus_image_method_rename, SD_BUS_VTABLE_UNPRIVILEGED),
196 SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED),
197 SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
201 static int image_flush_cache(sd_event_source *s, void *userdata) {
202 Manager *m = userdata;
208 while ((i = hashmap_steal_first(m->image_cache)))
214 int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
215 _cleanup_free_ char *e = NULL;
216 Manager *m = userdata;
226 p = startswith(path, "/org/freedesktop/machine1/image/");
230 e = bus_label_unescape(p);
234 image = hashmap_get(m->image_cache, e);
240 r = hashmap_ensure_allocated(&m->image_cache, &string_hash_ops);
244 if (!m->image_cache_defer_event) {
245 r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_flush_cache, m);
249 r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE);
254 r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT);
258 r = image_find(e, &image);
264 r = hashmap_put(m->image_cache, image->name, image);
274 char *image_bus_path(const char *name) {
275 _cleanup_free_ char *e = NULL;
279 e = bus_label_escape(name);
283 return strappend("/org/freedesktop/machine1/image/", e);
286 int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
287 _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
288 _cleanup_strv_free_ char **l = NULL;
297 images = hashmap_new(&string_hash_ops);
301 r = image_discover(images);
305 HASHMAP_FOREACH(image, images, i) {
308 p = image_bus_path(image->name);
312 r = strv_consume(&l, p);