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