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