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",
53 return 1; /* Will call us back */
55 r
= image_remove(image
);
59 return sd_bus_reply_method_return(message
, NULL
);
62 int bus_image_method_rename(
63 sd_bus_message
*message
,
65 sd_bus_error
*error
) {
67 Image
*image
= userdata
;
68 Manager
*m
= image
->userdata
;
75 r
= sd_bus_message_read(message
, "s", &new_name
);
79 if (!image_name_is_valid(new_name
))
80 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", new_name
);
82 r
= bus_verify_polkit_async(
85 "org.freedesktop.machine1.manage-images",
93 return 1; /* Will call us back */
95 r
= image_rename(image
, new_name
);
99 return sd_bus_reply_method_return(message
, NULL
);
102 int bus_image_method_clone(
103 sd_bus_message
*message
,
105 sd_bus_error
*error
) {
107 Image
*image
= userdata
;
108 Manager
*m
= image
->userdata
;
109 const char *new_name
;
115 r
= sd_bus_message_read(message
, "sb", &new_name
, &read_only
);
119 if (!image_name_is_valid(new_name
))
120 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", new_name
);
122 r
= bus_verify_polkit_async(
125 "org.freedesktop.machine1.manage-images",
133 return 1; /* Will call us back */
135 r
= image_clone(image
, new_name
, read_only
);
139 return sd_bus_reply_method_return(message
, NULL
);
142 int bus_image_method_mark_read_only(
143 sd_bus_message
*message
,
145 sd_bus_error
*error
) {
147 Image
*image
= userdata
;
148 Manager
*m
= image
->userdata
;
153 r
= sd_bus_message_read(message
, "b", &read_only
);
157 r
= bus_verify_polkit_async(
160 "org.freedesktop.machine1.manage-images",
168 return 1; /* Will call us back */
170 r
= image_read_only(image
, read_only
);
174 return sd_bus_reply_method_return(message
, NULL
);
177 int bus_image_method_set_limit(
178 sd_bus_message
*message
,
180 sd_bus_error
*error
) {
182 Image
*image
= userdata
;
183 Manager
*m
= image
->userdata
;
189 r
= sd_bus_message_read(message
, "t", &limit
);
193 r
= bus_verify_polkit_async(
196 "org.freedesktop.machine1.manage-images",
204 return 1; /* Will call us back */
206 r
= image_set_limit(image
, limit
);
210 return sd_bus_reply_method_return(message
, NULL
);
213 const sd_bus_vtable image_vtable
[] = {
214 SD_BUS_VTABLE_START(0),
215 SD_BUS_PROPERTY("Name", "s", NULL
, offsetof(Image
, name
), 0),
216 SD_BUS_PROPERTY("Path", "s", NULL
, offsetof(Image
, path
), 0),
217 SD_BUS_PROPERTY("Type", "s", property_get_type
, offsetof(Image
, type
), 0),
218 SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool
, offsetof(Image
, read_only
), 0),
219 SD_BUS_PROPERTY("CreationTimestamp", "t", NULL
, offsetof(Image
, crtime
), 0),
220 SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL
, offsetof(Image
, mtime
), 0),
221 SD_BUS_PROPERTY("Usage", "t", NULL
, offsetof(Image
, usage
), 0),
222 SD_BUS_PROPERTY("Limit", "t", NULL
, offsetof(Image
, limit
), 0),
223 SD_BUS_PROPERTY("UsageExclusive", "t", NULL
, offsetof(Image
, usage_exclusive
), 0),
224 SD_BUS_PROPERTY("LimitExclusive", "t", NULL
, offsetof(Image
, limit_exclusive
), 0),
225 SD_BUS_METHOD("Remove", NULL
, NULL
, bus_image_method_remove
, SD_BUS_VTABLE_UNPRIVILEGED
),
226 SD_BUS_METHOD("Rename", "s", NULL
, bus_image_method_rename
, SD_BUS_VTABLE_UNPRIVILEGED
),
227 SD_BUS_METHOD("Clone", "sb", NULL
, bus_image_method_clone
, SD_BUS_VTABLE_UNPRIVILEGED
),
228 SD_BUS_METHOD("MarkReadOnly", "b", NULL
, bus_image_method_mark_read_only
, SD_BUS_VTABLE_UNPRIVILEGED
),
229 SD_BUS_METHOD("SetLimit", "t", NULL
, bus_image_method_set_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
233 static int image_flush_cache(sd_event_source
*s
, void *userdata
) {
234 Manager
*m
= userdata
;
240 while ((i
= hashmap_steal_first(m
->image_cache
)))
246 int image_object_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
247 _cleanup_free_
char *e
= NULL
;
248 Manager
*m
= userdata
;
258 p
= startswith(path
, "/org/freedesktop/machine1/image/");
262 e
= bus_label_unescape(p
);
266 image
= hashmap_get(m
->image_cache
, e
);
272 r
= hashmap_ensure_allocated(&m
->image_cache
, &string_hash_ops
);
276 if (!m
->image_cache_defer_event
) {
277 r
= sd_event_add_defer(m
->event
, &m
->image_cache_defer_event
, image_flush_cache
, m
);
281 r
= sd_event_source_set_priority(m
->image_cache_defer_event
, SD_EVENT_PRIORITY_IDLE
);
286 r
= sd_event_source_set_enabled(m
->image_cache_defer_event
, SD_EVENT_ONESHOT
);
290 r
= image_find(e
, &image
);
296 r
= hashmap_put(m
->image_cache
, image
->name
, image
);
306 char *image_bus_path(const char *name
) {
307 _cleanup_free_
char *e
= NULL
;
311 e
= bus_label_escape(name
);
315 return strappend("/org/freedesktop/machine1/image/", e
);
318 int image_node_enumerator(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
319 _cleanup_(image_hashmap_freep
) Hashmap
*images
= NULL
;
320 _cleanup_strv_free_
char **l
= NULL
;
329 images
= hashmap_new(&string_hash_ops
);
333 r
= image_discover(images
);
337 HASHMAP_FOREACH(image
, images
, i
) {
340 p
= image_bus_path(image
->name
);
344 r
= strv_consume(&l
, p
);