]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/machine/image-dbus.c
Merge pull request #1140 from poettering/sd-event-signals
[thirdparty/systemd.git] / src / machine / image-dbus.c
CommitLineData
ebeccf9e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
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.
12
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.
17
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/>.
20***/
21
22#include "bus-label.h"
ebeccf9e 23#include "strv.h"
1ddb263d 24#include "bus-util.h"
003dffde
LP
25#include "machine-image.h"
26#include "image-dbus.h"
ebeccf9e 27
1ddb263d 28static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, image_type, ImageType);
ebeccf9e 29
1ddb263d 30int bus_image_method_remove(
08682124
LP
31 sd_bus_message *message,
32 void *userdata,
33 sd_bus_error *error) {
34
1ddb263d 35 Image *image = userdata;
70244d1d 36 Manager *m = image->userdata;
08682124
LP
37 int r;
38
08682124 39 assert(message);
1ddb263d 40 assert(image);
08682124 41
70244d1d
LP
42 r = bus_verify_polkit_async(
43 message,
44 CAP_SYS_ADMIN,
45 "org.freedesktop.machine1.manage-images",
46 false,
c529695e 47 UID_INVALID,
70244d1d
LP
48 &m->polkit_registry,
49 error);
50 if (r < 0)
51 return r;
52 if (r == 0)
53 return 1; /* Will call us back */
54
08682124
LP
55 r = image_remove(image);
56 if (r < 0)
57 return r;
58
59 return sd_bus_reply_method_return(message, NULL);
60}
61
1ddb263d 62int bus_image_method_rename(
ebd93cb6
LP
63 sd_bus_message *message,
64 void *userdata,
65 sd_bus_error *error) {
66
1ddb263d 67 Image *image = userdata;
70244d1d 68 Manager *m = image->userdata;
ebd93cb6
LP
69 const char *new_name;
70 int r;
71
ebd93cb6 72 assert(message);
1ddb263d 73 assert(image);
ebd93cb6
LP
74
75 r = sd_bus_message_read(message, "s", &new_name);
76 if (r < 0)
77 return r;
78
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);
81
70244d1d
LP
82 r = bus_verify_polkit_async(
83 message,
84 CAP_SYS_ADMIN,
85 "org.freedesktop.machine1.manage-images",
86 false,
c529695e 87 UID_INVALID,
70244d1d
LP
88 &m->polkit_registry,
89 error);
90 if (r < 0)
91 return r;
92 if (r == 0)
93 return 1; /* Will call us back */
94
ebd93cb6
LP
95 r = image_rename(image, new_name);
96 if (r < 0)
97 return r;
98
99 return sd_bus_reply_method_return(message, NULL);
100}
101
1ddb263d 102int bus_image_method_clone(
ebd93cb6
LP
103 sd_bus_message *message,
104 void *userdata,
105 sd_bus_error *error) {
106
1ddb263d 107 Image *image = userdata;
70244d1d 108 Manager *m = image->userdata;
ebd93cb6
LP
109 const char *new_name;
110 int r, read_only;
111
ebd93cb6 112 assert(message);
1ddb263d 113 assert(image);
ebd93cb6
LP
114
115 r = sd_bus_message_read(message, "sb", &new_name, &read_only);
116 if (r < 0)
117 return r;
118
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);
121
70244d1d
LP
122 r = bus_verify_polkit_async(
123 message,
124 CAP_SYS_ADMIN,
125 "org.freedesktop.machine1.manage-images",
126 false,
c529695e 127 UID_INVALID,
70244d1d
LP
128 &m->polkit_registry,
129 error);
130 if (r < 0)
131 return r;
132 if (r == 0)
133 return 1; /* Will call us back */
134
ebd93cb6
LP
135 r = image_clone(image, new_name, read_only);
136 if (r < 0)
137 return r;
138
139 return sd_bus_reply_method_return(message, NULL);
140}
141
1ddb263d 142int bus_image_method_mark_read_only(
ebd93cb6
LP
143 sd_bus_message *message,
144 void *userdata,
145 sd_bus_error *error) {
146
1ddb263d 147 Image *image = userdata;
70244d1d 148 Manager *m = image->userdata;
ebd93cb6
LP
149 int r, read_only;
150
ebd93cb6
LP
151 assert(message);
152
ebd93cb6
LP
153 r = sd_bus_message_read(message, "b", &read_only);
154 if (r < 0)
155 return r;
156
70244d1d
LP
157 r = bus_verify_polkit_async(
158 message,
159 CAP_SYS_ADMIN,
160 "org.freedesktop.machine1.manage-images",
161 false,
c529695e 162 UID_INVALID,
70244d1d
LP
163 &m->polkit_registry,
164 error);
165 if (r < 0)
166 return r;
167 if (r == 0)
168 return 1; /* Will call us back */
169
ebd93cb6
LP
170 r = image_read_only(image, read_only);
171 if (r < 0)
172 return r;
173
174 return sd_bus_reply_method_return(message, NULL);
175}
176
d6ce17c7 177int bus_image_method_set_limit(
d6ce17c7
LP
178 sd_bus_message *message,
179 void *userdata,
180 sd_bus_error *error) {
181
182 Image *image = userdata;
183 Manager *m = image->userdata;
184 uint64_t limit;
185 int r;
186
d6ce17c7
LP
187 assert(message);
188
189 r = sd_bus_message_read(message, "t", &limit);
190 if (r < 0)
191 return r;
192
193 r = bus_verify_polkit_async(
194 message,
195 CAP_SYS_ADMIN,
196 "org.freedesktop.machine1.manage-images",
197 false,
198 UID_INVALID,
199 &m->polkit_registry,
200 error);
201 if (r < 0)
202 return r;
203 if (r == 0)
204 return 1; /* Will call us back */
205
206 r = image_set_limit(image, limit);
207 if (r < 0)
208 return r;
209
210 return sd_bus_reply_method_return(message, NULL);
211}
212
ebeccf9e
LP
213const sd_bus_vtable image_vtable[] = {
214 SD_BUS_VTABLE_START(0),
1ddb263d
LP
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),
c19de711 221 SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0),
1ddb263d 222 SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0),
c19de711 223 SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0),
1ddb263d 224 SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0),
70244d1d
LP
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),
d6ce17c7 229 SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED),
ebeccf9e
LP
230 SD_BUS_VTABLE_END
231};
232
1ddb263d
LP
233static int image_flush_cache(sd_event_source *s, void *userdata) {
234 Manager *m = userdata;
235 Image *i;
236
237 assert(s);
238 assert(m);
239
240 while ((i = hashmap_steal_first(m->image_cache)))
241 image_unref(i);
242
243 return 0;
244}
245
ebeccf9e 246int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
1ddb263d
LP
247 _cleanup_free_ char *e = NULL;
248 Manager *m = userdata;
249 Image *image = NULL;
250 const char *p;
ebeccf9e
LP
251 int r;
252
253 assert(bus);
254 assert(path);
255 assert(interface);
256 assert(found);
257
1ddb263d
LP
258 p = startswith(path, "/org/freedesktop/machine1/image/");
259 if (!p)
260 return 0;
261
262 e = bus_label_unescape(p);
263 if (!e)
264 return -ENOMEM;
265
266 image = hashmap_get(m->image_cache, e);
267 if (image) {
268 *found = image;
269 return 1;
270 }
271
272 r = hashmap_ensure_allocated(&m->image_cache, &string_hash_ops);
273 if (r < 0)
274 return r;
275
276 if (!m->image_cache_defer_event) {
277 r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_flush_cache, m);
278 if (r < 0)
279 return r;
280
281 r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE);
282 if (r < 0)
283 return r;
284 }
285
286 r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT);
287 if (r < 0)
288 return r;
289
290 r = image_find(e, &image);
ebeccf9e
LP
291 if (r <= 0)
292 return r;
293
70244d1d
LP
294 image->userdata = m;
295
1ddb263d
LP
296 r = hashmap_put(m->image_cache, image->name, image);
297 if (r < 0) {
298 image_unref(image);
299 return r;
300 }
301
302 *found = image;
ebeccf9e
LP
303 return 1;
304}
305
306char *image_bus_path(const char *name) {
307 _cleanup_free_ char *e = NULL;
308
309 assert(name);
310
311 e = bus_label_escape(name);
312 if (!e)
313 return NULL;
314
315 return strappend("/org/freedesktop/machine1/image/", e);
316}
317
318int 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;
321 Image *image;
322 Iterator i;
323 int r;
324
325 assert(bus);
326 assert(path);
327 assert(nodes);
328
329 images = hashmap_new(&string_hash_ops);
330 if (!images)
331 return -ENOMEM;
332
333 r = image_discover(images);
334 if (r < 0)
335 return r;
336
337 HASHMAP_FOREACH(image, images, i) {
338 char *p;
339
340 p = image_bus_path(image->name);
341 if (!p)
342 return -ENOMEM;
343
344 r = strv_consume(&l, p);
345 if (r < 0)
346 return r;
347 }
348
349 *nodes = l;
350 l = NULL;
351
352 return 1;
353}