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(
31 sd_bus_message
*message
,
33 sd_bus_error
*error
) {
35 Image
*image
= userdata
;
36 Manager
*m
= image
->userdata
;
42 r
= bus_verify_polkit_async(
45 "org.freedesktop.machine1.manage-images",
54 return 1; /* Will call us back */
56 r
= image_remove(image
);
60 return sd_bus_reply_method_return(message
, NULL
);
63 int bus_image_method_rename(
64 sd_bus_message
*message
,
66 sd_bus_error
*error
) {
68 Image
*image
= userdata
;
69 Manager
*m
= image
->userdata
;
76 r
= sd_bus_message_read(message
, "s", &new_name
);
80 if (!image_name_is_valid(new_name
))
81 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", new_name
);
83 r
= bus_verify_polkit_async(
86 "org.freedesktop.machine1.manage-images",
95 return 1; /* Will call us back */
97 r
= image_rename(image
, new_name
);
101 return sd_bus_reply_method_return(message
, NULL
);
104 int bus_image_method_clone(
105 sd_bus_message
*message
,
107 sd_bus_error
*error
) {
109 Image
*image
= userdata
;
110 Manager
*m
= image
->userdata
;
111 const char *new_name
;
117 r
= sd_bus_message_read(message
, "sb", &new_name
, &read_only
);
121 if (!image_name_is_valid(new_name
))
122 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", new_name
);
124 r
= bus_verify_polkit_async(
127 "org.freedesktop.machine1.manage-images",
136 return 1; /* Will call us back */
138 r
= image_clone(image
, new_name
, read_only
);
142 return sd_bus_reply_method_return(message
, NULL
);
145 int bus_image_method_mark_read_only(
146 sd_bus_message
*message
,
148 sd_bus_error
*error
) {
150 Image
*image
= userdata
;
151 Manager
*m
= image
->userdata
;
156 r
= sd_bus_message_read(message
, "b", &read_only
);
160 r
= bus_verify_polkit_async(
163 "org.freedesktop.machine1.manage-images",
172 return 1; /* Will call us back */
174 r
= image_read_only(image
, read_only
);
178 return sd_bus_reply_method_return(message
, NULL
);
181 int bus_image_method_set_limit(
182 sd_bus_message
*message
,
184 sd_bus_error
*error
) {
186 Image
*image
= userdata
;
187 Manager
*m
= image
->userdata
;
193 r
= sd_bus_message_read(message
, "t", &limit
);
197 r
= bus_verify_polkit_async(
200 "org.freedesktop.machine1.manage-images",
209 return 1; /* Will call us back */
211 r
= image_set_limit(image
, limit
);
215 return sd_bus_reply_method_return(message
, NULL
);
218 const sd_bus_vtable image_vtable
[] = {
219 SD_BUS_VTABLE_START(0),
220 SD_BUS_PROPERTY("Name", "s", NULL
, offsetof(Image
, name
), 0),
221 SD_BUS_PROPERTY("Path", "s", NULL
, offsetof(Image
, path
), 0),
222 SD_BUS_PROPERTY("Type", "s", property_get_type
, offsetof(Image
, type
), 0),
223 SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool
, offsetof(Image
, read_only
), 0),
224 SD_BUS_PROPERTY("CreationTimestamp", "t", NULL
, offsetof(Image
, crtime
), 0),
225 SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL
, offsetof(Image
, mtime
), 0),
226 SD_BUS_PROPERTY("Usage", "t", NULL
, offsetof(Image
, usage
), 0),
227 SD_BUS_PROPERTY("Limit", "t", NULL
, offsetof(Image
, limit
), 0),
228 SD_BUS_PROPERTY("UsageExclusive", "t", NULL
, offsetof(Image
, usage_exclusive
), 0),
229 SD_BUS_PROPERTY("LimitExclusive", "t", NULL
, offsetof(Image
, limit_exclusive
), 0),
230 SD_BUS_METHOD("Remove", NULL
, NULL
, bus_image_method_remove
, SD_BUS_VTABLE_UNPRIVILEGED
),
231 SD_BUS_METHOD("Rename", "s", NULL
, bus_image_method_rename
, SD_BUS_VTABLE_UNPRIVILEGED
),
232 SD_BUS_METHOD("Clone", "sb", NULL
, bus_image_method_clone
, SD_BUS_VTABLE_UNPRIVILEGED
),
233 SD_BUS_METHOD("MarkReadOnly", "b", NULL
, bus_image_method_mark_read_only
, SD_BUS_VTABLE_UNPRIVILEGED
),
234 SD_BUS_METHOD("SetLimit", "t", NULL
, bus_image_method_set_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
238 static int image_flush_cache(sd_event_source
*s
, void *userdata
) {
239 Manager
*m
= userdata
;
245 while ((i
= hashmap_steal_first(m
->image_cache
)))
251 int image_object_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
252 _cleanup_free_
char *e
= NULL
;
253 Manager
*m
= userdata
;
263 p
= startswith(path
, "/org/freedesktop/machine1/image/");
267 e
= bus_label_unescape(p
);
271 image
= hashmap_get(m
->image_cache
, e
);
277 r
= hashmap_ensure_allocated(&m
->image_cache
, &string_hash_ops
);
281 if (!m
->image_cache_defer_event
) {
282 r
= sd_event_add_defer(m
->event
, &m
->image_cache_defer_event
, image_flush_cache
, m
);
286 r
= sd_event_source_set_priority(m
->image_cache_defer_event
, SD_EVENT_PRIORITY_IDLE
);
291 r
= sd_event_source_set_enabled(m
->image_cache_defer_event
, SD_EVENT_ONESHOT
);
295 r
= image_find(e
, &image
);
301 r
= hashmap_put(m
->image_cache
, image
->name
, image
);
311 char *image_bus_path(const char *name
) {
312 _cleanup_free_
char *e
= NULL
;
316 e
= bus_label_escape(name
);
320 return strappend("/org/freedesktop/machine1/image/", e
);
323 int image_node_enumerator(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
324 _cleanup_(image_hashmap_freep
) Hashmap
*images
= NULL
;
325 _cleanup_strv_free_
char **l
= NULL
;
334 images
= hashmap_new(&string_hash_ops
);
338 r
= image_discover(images
);
342 HASHMAP_FOREACH(image
, images
, i
) {
345 p
= image_bus_path(image
->name
);
349 r
= strv_consume(&l
, p
);