]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/machine/image-dbus.c
sd-bus: drop bus parameter from message callback prototype
[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 false,
47 UID_INVALID,
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
55 r = image_remove(image);
56 if (r < 0)
57 return r;
58
59 return sd_bus_reply_method_return(message, NULL);
60 }
61
62 int bus_image_method_rename(
63 sd_bus_message *message,
64 void *userdata,
65 sd_bus_error *error) {
66
67 Image *image = userdata;
68 Manager *m = image->userdata;
69 const char *new_name;
70 int r;
71
72 assert(message);
73 assert(image);
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
82 r = bus_verify_polkit_async(
83 message,
84 CAP_SYS_ADMIN,
85 "org.freedesktop.machine1.manage-images",
86 false,
87 UID_INVALID,
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
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
102 int bus_image_method_clone(
103 sd_bus_message *message,
104 void *userdata,
105 sd_bus_error *error) {
106
107 Image *image = userdata;
108 Manager *m = image->userdata;
109 const char *new_name;
110 int r, read_only;
111
112 assert(message);
113 assert(image);
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
122 r = bus_verify_polkit_async(
123 message,
124 CAP_SYS_ADMIN,
125 "org.freedesktop.machine1.manage-images",
126 false,
127 UID_INVALID,
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
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
142 int bus_image_method_mark_read_only(
143 sd_bus_message *message,
144 void *userdata,
145 sd_bus_error *error) {
146
147 Image *image = userdata;
148 Manager *m = image->userdata;
149 int r, read_only;
150
151 assert(message);
152
153 r = sd_bus_message_read(message, "b", &read_only);
154 if (r < 0)
155 return r;
156
157 r = bus_verify_polkit_async(
158 message,
159 CAP_SYS_ADMIN,
160 "org.freedesktop.machine1.manage-images",
161 false,
162 UID_INVALID,
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
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
177 int bus_image_method_set_limit(
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
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
213 const sd_bus_vtable image_vtable[] = {
214 SD_BUS_VTABLE_START(0),
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),
221 SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0),
222 SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0),
223 SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0),
224 SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0),
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),
229 SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED),
230 SD_BUS_VTABLE_END
231 };
232
233 static 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
246 int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
247 _cleanup_free_ char *e = NULL;
248 Manager *m = userdata;
249 Image *image = NULL;
250 const char *p;
251 int r;
252
253 assert(bus);
254 assert(path);
255 assert(interface);
256 assert(found);
257
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);
291 if (r <= 0)
292 return r;
293
294 image->userdata = m;
295
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;
303 return 1;
304 }
305
306 char *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
318 int 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 }