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