chiark / gitweb /
machined: beef up machined image listing with creation/modification times of subvolumes
[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 "bus-common-errors.h"
24 #include "strv.h"
25 #include "image.h"
26
27 static int image_find_by_bus_path(const char *path, Image **ret) {
28         _cleanup_free_ char *e = NULL;
29         const char *p;
30
31         assert(path);
32
33         p = startswith(path, "/org/freedesktop/machine1/image/");
34         if (!p)
35                 return 0;
36
37         e = bus_label_unescape(p);
38         if (!e)
39                 return -ENOMEM;
40
41         return image_find(e, ret);
42 }
43
44 static int image_find_by_bus_path_with_error(const char *path, Image **ret, sd_bus_error *error) {
45         int r;
46
47         assert(path);
48
49         r = image_find_by_bus_path(path, ret);
50         if (r == 0)
51                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "Image doesn't exist.");
52
53         return r;
54 }
55
56 static int property_get_name(
57                 sd_bus *bus,
58                 const char *path,
59                 const char *interface,
60                 const char *property,
61                 sd_bus_message *reply,
62                 void *userdata,
63                 sd_bus_error *error) {
64
65         _cleanup_(image_unrefp) Image *image = NULL;
66         int r;
67
68         assert(bus);
69         assert(reply);
70
71         r = image_find_by_bus_path_with_error(path, &image, error);
72         if (r < 0)
73                 return r;
74
75         r = sd_bus_message_append(reply, "s", image->name);
76         if (r < 0)
77                 return r;
78
79         return 1;
80 }
81
82 static int property_get_path(
83                 sd_bus *bus,
84                 const char *path,
85                 const char *interface,
86                 const char *property,
87                 sd_bus_message *reply,
88                 void *userdata,
89                 sd_bus_error *error) {
90
91         _cleanup_(image_unrefp) Image *image = NULL;
92         int r;
93
94         assert(bus);
95         assert(reply);
96
97         r = image_find_by_bus_path_with_error(path, &image, error);
98         if (r < 0)
99                 return r;
100
101         r = sd_bus_message_append(reply, "s", image->path);
102         if (r < 0)
103                 return r;
104
105         return 1;
106 }
107
108 static int property_get_type(
109                 sd_bus *bus,
110                 const char *path,
111                 const char *interface,
112                 const char *property,
113                 sd_bus_message *reply,
114                 void *userdata,
115                 sd_bus_error *error) {
116
117
118         _cleanup_(image_unrefp) Image *image = NULL;
119         int r;
120
121         assert(bus);
122         assert(reply);
123
124         r = image_find_by_bus_path_with_error(path, &image, error);
125         if (r < 0)
126                 return r;
127
128         r = sd_bus_message_append(reply, "s", image_type_to_string(image->type));
129         if (r < 0)
130                 return r;
131
132         return 1;
133 }
134
135 static int property_get_read_only(
136                 sd_bus *bus,
137                 const char *path,
138                 const char *interface,
139                 const char *property,
140                 sd_bus_message *reply,
141                 void *userdata,
142                 sd_bus_error *error) {
143
144
145         _cleanup_(image_unrefp) Image *image = NULL;
146         int r;
147
148         assert(bus);
149         assert(reply);
150
151         r = image_find_by_bus_path_with_error(path, &image, error);
152         if (r < 0)
153                 return r;
154
155         r = sd_bus_message_append(reply, "b", image->read_only);
156         if (r < 0)
157                 return r;
158
159         return 1;
160 }
161
162 static int property_get_crtime(
163                 sd_bus *bus,
164                 const char *path,
165                 const char *interface,
166                 const char *property,
167                 sd_bus_message *reply,
168                 void *userdata,
169                 sd_bus_error *error) {
170
171
172         _cleanup_(image_unrefp) Image *image = NULL;
173         int r;
174
175         assert(bus);
176         assert(reply);
177
178         r = image_find_by_bus_path_with_error(path, &image, error);
179         if (r < 0)
180                 return r;
181
182         r = sd_bus_message_append(reply, "t", image->crtime);
183         if (r < 0)
184                 return r;
185
186         return 1;
187 }
188
189 static int property_get_mtime(
190                 sd_bus *bus,
191                 const char *path,
192                 const char *interface,
193                 const char *property,
194                 sd_bus_message *reply,
195                 void *userdata,
196                 sd_bus_error *error) {
197
198
199         _cleanup_(image_unrefp) Image *image = NULL;
200         int r;
201
202         assert(bus);
203         assert(reply);
204
205         r = image_find_by_bus_path_with_error(path, &image, error);
206         if (r < 0)
207                 return r;
208
209         r = sd_bus_message_append(reply, "t", image->mtime);
210         if (r < 0)
211                 return r;
212
213         return 1;
214 }
215
216 const sd_bus_vtable image_vtable[] = {
217         SD_BUS_VTABLE_START(0),
218         SD_BUS_PROPERTY("Name",                  "s", property_get_name,      0, 0),
219         SD_BUS_PROPERTY("Path",                  "s", property_get_path,      0, 0),
220         SD_BUS_PROPERTY("Type",                  "s", property_get_type,      0, 0),
221         SD_BUS_PROPERTY("ReadOnly",              "b", property_get_read_only, 0, 0),
222         SD_BUS_PROPERTY("CreationTimestamp",     "t", property_get_crtime,    0, 0),
223         SD_BUS_PROPERTY("ModificationTimestamp", "t", property_get_mtime,     0, 0),
224         SD_BUS_VTABLE_END
225 };
226
227 int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
228         int r;
229
230         assert(bus);
231         assert(path);
232         assert(interface);
233         assert(found);
234
235         r = image_find_by_bus_path(path, NULL);
236         if (r <= 0)
237                 return r;
238
239         *found = NULL;
240         return 1;
241 }
242
243 char *image_bus_path(const char *name) {
244         _cleanup_free_ char *e = NULL;
245
246         assert(name);
247
248         e = bus_label_escape(name);
249         if (!e)
250                 return NULL;
251
252         return strappend("/org/freedesktop/machine1/image/", e);
253 }
254
255 int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
256         _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
257         _cleanup_strv_free_ char **l = NULL;
258         Image *image;
259         Iterator i;
260         int r;
261
262         assert(bus);
263         assert(path);
264         assert(nodes);
265
266         images = hashmap_new(&string_hash_ops);
267         if (!images)
268                 return -ENOMEM;
269
270         r = image_discover(images);
271         if (r < 0)
272                 return r;
273
274         HASHMAP_FOREACH(image, images, i) {
275                 char *p;
276
277                 p = image_bus_path(image->name);
278                 if (!p)
279                         return -ENOMEM;
280
281                 r = strv_consume(&l, p);
282                 if (r < 0)
283                         return r;
284         }
285
286         *nodes = l;
287         l = NULL;
288
289         return 1;
290 }