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",
56 return 1; /* Will call us back */
58 r = image_remove(image);
62 return sd_bus_reply_method_return(message, NULL);
65 int bus_image_method_rename(
67 sd_bus_message *message,
69 sd_bus_error *error) {
71 Image *image = userdata;
72 Manager *m = image->userdata;
80 r = sd_bus_message_read(message, "s", &new_name);
84 if (!image_name_is_valid(new_name))
85 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
87 r = bus_verify_polkit_async(
90 "org.freedesktop.machine1.manage-images",
98 return 1; /* Will call us back */
100 r = image_rename(image, new_name);
104 return sd_bus_reply_method_return(message, NULL);
107 int bus_image_method_clone(
109 sd_bus_message *message,
111 sd_bus_error *error) {
113 Image *image = userdata;
114 Manager *m = image->userdata;
115 const char *new_name;
122 r = sd_bus_message_read(message, "sb", &new_name, &read_only);
126 if (!image_name_is_valid(new_name))
127 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
129 r = bus_verify_polkit_async(
132 "org.freedesktop.machine1.manage-images",
140 return 1; /* Will call us back */
142 r = image_clone(image, new_name, read_only);
146 return sd_bus_reply_method_return(message, NULL);
149 int bus_image_method_mark_read_only(
151 sd_bus_message *message,
153 sd_bus_error *error) {
155 Image *image = userdata;
156 Manager *m = image->userdata;
162 r = sd_bus_message_read(message, "b", &read_only);
166 r = bus_verify_polkit_async(
169 "org.freedesktop.machine1.manage-images",
177 return 1; /* Will call us back */
179 r = image_read_only(image, read_only);
183 return sd_bus_reply_method_return(message, NULL);
186 const sd_bus_vtable image_vtable[] = {
187 SD_BUS_VTABLE_START(0),
188 SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0),
189 SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0),
190 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0),
191 SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0),
192 SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0),
193 SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0),
194 SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0),
195 SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0),
196 SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0),
197 SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0),
198 SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
199 SD_BUS_METHOD("Rename", "s", NULL, bus_image_method_rename, SD_BUS_VTABLE_UNPRIVILEGED),
200 SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED),
201 SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
205 static int image_flush_cache(sd_event_source *s, void *userdata) {
206 Manager *m = userdata;
212 while ((i = hashmap_steal_first(m->image_cache)))
218 int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
219 _cleanup_free_ char *e = NULL;
220 Manager *m = userdata;
230 p = startswith(path, "/org/freedesktop/machine1/image/");
234 e = bus_label_unescape(p);
238 image = hashmap_get(m->image_cache, e);
244 r = hashmap_ensure_allocated(&m->image_cache, &string_hash_ops);
248 if (!m->image_cache_defer_event) {
249 r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_flush_cache, m);
253 r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE);
258 r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT);
262 r = image_find(e, &image);
268 r = hashmap_put(m->image_cache, image->name, image);
278 char *image_bus_path(const char *name) {
279 _cleanup_free_ char *e = NULL;
283 e = bus_label_escape(name);
287 return strappend("/org/freedesktop/machine1/image/", e);
290 int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
291 _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
292 _cleanup_strv_free_ char **l = NULL;
301 images = hashmap_new(&string_hash_ops);
305 r = image_discover(images);
309 HASHMAP_FOREACH(image, images, i) {
312 p = image_bus_path(image->name);
316 r = strv_consume(&l, p);