2 This file is part of systemd.
4 Copyright 2014 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "alloc-util.h"
21 #include "bus-label.h"
23 #include "image-dbus.h"
25 #include "machine-image.h"
27 #include "user-util.h"
29 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type
, image_type
, ImageType
);
31 int bus_image_method_remove(
32 sd_bus_message
*message
,
34 sd_bus_error
*error
) {
36 Image
*image
= userdata
;
37 Manager
*m
= image
->userdata
;
43 r
= bus_verify_polkit_async(
46 "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(
65 sd_bus_message
*message
,
67 sd_bus_error
*error
) {
69 Image
*image
= userdata
;
70 Manager
*m
= image
->userdata
;
77 r
= sd_bus_message_read(message
, "s", &new_name
);
81 if (!image_name_is_valid(new_name
))
82 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", new_name
);
84 r
= bus_verify_polkit_async(
87 "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(
106 sd_bus_message
*message
,
108 sd_bus_error
*error
) {
110 Image
*image
= userdata
;
111 Manager
*m
= image
->userdata
;
112 const char *new_name
;
118 r
= sd_bus_message_read(message
, "sb", &new_name
, &read_only
);
122 if (!image_name_is_valid(new_name
))
123 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", new_name
);
125 r
= bus_verify_polkit_async(
128 "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(
147 sd_bus_message
*message
,
149 sd_bus_error
*error
) {
151 Image
*image
= userdata
;
152 Manager
*m
= image
->userdata
;
157 r
= sd_bus_message_read(message
, "b", &read_only
);
161 r
= bus_verify_polkit_async(
164 "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 int bus_image_method_set_limit(
183 sd_bus_message
*message
,
185 sd_bus_error
*error
) {
187 Image
*image
= userdata
;
188 Manager
*m
= image
->userdata
;
194 r
= sd_bus_message_read(message
, "t", &limit
);
197 if (!FILE_SIZE_VALID_OR_INFINITY(limit
))
198 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "New limit out of range");
200 r
= bus_verify_polkit_async(
203 "org.freedesktop.machine1.manage-images",
212 return 1; /* Will call us back */
214 r
= image_set_limit(image
, limit
);
218 return sd_bus_reply_method_return(message
, NULL
);
221 const sd_bus_vtable image_vtable
[] = {
222 SD_BUS_VTABLE_START(0),
223 SD_BUS_PROPERTY("Name", "s", NULL
, offsetof(Image
, name
), 0),
224 SD_BUS_PROPERTY("Path", "s", NULL
, offsetof(Image
, path
), 0),
225 SD_BUS_PROPERTY("Type", "s", property_get_type
, offsetof(Image
, type
), 0),
226 SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool
, offsetof(Image
, read_only
), 0),
227 SD_BUS_PROPERTY("CreationTimestamp", "t", NULL
, offsetof(Image
, crtime
), 0),
228 SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL
, offsetof(Image
, mtime
), 0),
229 SD_BUS_PROPERTY("Usage", "t", NULL
, offsetof(Image
, usage
), 0),
230 SD_BUS_PROPERTY("Limit", "t", NULL
, offsetof(Image
, limit
), 0),
231 SD_BUS_PROPERTY("UsageExclusive", "t", NULL
, offsetof(Image
, usage_exclusive
), 0),
232 SD_BUS_PROPERTY("LimitExclusive", "t", NULL
, offsetof(Image
, limit_exclusive
), 0),
233 SD_BUS_METHOD("Remove", NULL
, NULL
, bus_image_method_remove
, SD_BUS_VTABLE_UNPRIVILEGED
),
234 SD_BUS_METHOD("Rename", "s", NULL
, bus_image_method_rename
, SD_BUS_VTABLE_UNPRIVILEGED
),
235 SD_BUS_METHOD("Clone", "sb", NULL
, bus_image_method_clone
, SD_BUS_VTABLE_UNPRIVILEGED
),
236 SD_BUS_METHOD("MarkReadOnly", "b", NULL
, bus_image_method_mark_read_only
, SD_BUS_VTABLE_UNPRIVILEGED
),
237 SD_BUS_METHOD("SetLimit", "t", NULL
, bus_image_method_set_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
241 static int image_flush_cache(sd_event_source
*s
, void *userdata
) {
242 Manager
*m
= userdata
;
248 while ((i
= hashmap_steal_first(m
->image_cache
)))
254 int image_object_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
255 _cleanup_free_
char *e
= NULL
;
256 Manager
*m
= userdata
;
266 p
= startswith(path
, "/org/freedesktop/machine1/image/");
270 e
= bus_label_unescape(p
);
274 image
= hashmap_get(m
->image_cache
, e
);
280 r
= hashmap_ensure_allocated(&m
->image_cache
, &string_hash_ops
);
284 if (!m
->image_cache_defer_event
) {
285 r
= sd_event_add_defer(m
->event
, &m
->image_cache_defer_event
, image_flush_cache
, m
);
289 r
= sd_event_source_set_priority(m
->image_cache_defer_event
, SD_EVENT_PRIORITY_IDLE
);
294 r
= sd_event_source_set_enabled(m
->image_cache_defer_event
, SD_EVENT_ONESHOT
);
298 r
= image_find(e
, &image
);
304 r
= hashmap_put(m
->image_cache
, image
->name
, image
);
314 char *image_bus_path(const char *name
) {
315 _cleanup_free_
char *e
= NULL
;
319 e
= bus_label_escape(name
);
323 return strappend("/org/freedesktop/machine1/image/", e
);
326 int image_node_enumerator(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
327 _cleanup_(image_hashmap_freep
) Hashmap
*images
= NULL
;
328 _cleanup_strv_free_
char **l
= NULL
;
337 images
= hashmap_new(&string_hash_ops
);
341 r
= image_discover(images
);
345 HASHMAP_FOREACH(image
, images
, i
) {
348 p
= image_bus_path(image
->name
);
352 r
= strv_consume(&l
, p
);