File: | build-scan/../src/portable/portablectl.c |
Warning: | line 718, column 24 Potential leak of memory pointed to by 'image' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include <errno(*__errno_location ()).h> | |||
4 | #include <getopt.h> | |||
5 | ||||
6 | #include "sd-bus.h" | |||
7 | ||||
8 | #include "alloc-util.h" | |||
9 | #include "bus-error.h" | |||
10 | #include "bus-util.h" | |||
11 | #include "def.h" | |||
12 | #include "dirent-util.h" | |||
13 | #include "fd-util.h" | |||
14 | #include "fileio.h" | |||
15 | #include "format-table.h" | |||
16 | #include "fs-util.h" | |||
17 | #include "locale-util.h" | |||
18 | #include "machine-image.h" | |||
19 | #include "pager.h" | |||
20 | #include "parse-util.h" | |||
21 | #include "path-util.h" | |||
22 | #include "spawn-polkit-agent.h" | |||
23 | #include "string-util.h" | |||
24 | #include "strv.h" | |||
25 | #include "terminal-util.h" | |||
26 | #include "verbs.h" | |||
27 | ||||
28 | static bool_Bool arg_no_pager = false0; | |||
29 | static bool_Bool arg_legend = true1; | |||
30 | static bool_Bool arg_ask_password = true1; | |||
31 | static bool_Bool arg_quiet = false0; | |||
32 | static const char *arg_profile = "default"; | |||
33 | static const char* arg_copy_mode = NULL((void*)0); | |||
34 | static bool_Bool arg_runtime = false0; | |||
35 | static bool_Bool arg_reload = true1; | |||
36 | static bool_Bool arg_cat = false0; | |||
37 | static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; | |||
38 | static char *arg_host = NULL((void*)0); | |||
39 | ||||
40 | static int determine_image(const char *image, bool_Bool permit_non_existing, char **ret) { | |||
41 | int r; | |||
42 | ||||
43 | /* If the specified name is a valid image name, we pass it as-is to portabled, which will search for it in the | |||
44 | * usual search directories. Otherwise we presume it's a path, and will normalize it on the client's side | |||
45 | * (among other things, to make the path independent of the client's working directory) before passing it | |||
46 | * over. */ | |||
47 | ||||
48 | if (image_name_is_valid(image)) { | |||
49 | char *c; | |||
50 | ||||
51 | if (!arg_quiet && laccess(image, F_OK)faccessat(-100, (image), (0), 0x100) >= 0) | |||
52 | log_warning("Ambiguous invocation: current working directory contains file matching non-path argument '%s', ignoring. "({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 53, __func__, "Ambiguous invocation: current working directory contains file matching non-path argument '%s', ignoring. " "Prefix argument with './' to force reference to file in current working directory." , image) : -abs(_e); }) | |||
53 | "Prefix argument with './' to force reference to file in current working directory.", image)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 53, __func__, "Ambiguous invocation: current working directory contains file matching non-path argument '%s', ignoring. " "Prefix argument with './' to force reference to file in current working directory." , image) : -abs(_e); }); | |||
54 | ||||
55 | c = strdup(image); | |||
56 | if (!c) | |||
57 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/portable/portablectl.c" , 57, __func__); | |||
58 | ||||
59 | *ret = c; | |||
60 | return 0; | |||
61 | } | |||
62 | ||||
63 | if (arg_transport != BUS_TRANSPORT_LOCAL) { | |||
64 | log_error("Operations on images by path not supported when connecting to remote systems.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 64, __func__, "Operations on images by path not supported when connecting to remote systems." ) : -abs(_e); }); | |||
65 | return -EOPNOTSUPP95; | |||
66 | } | |||
67 | ||||
68 | r = chase_symlinks(image, NULL((void*)0), CHASE_TRAIL_SLASH | (permit_non_existing ? CHASE_NONEXISTENT : 0), ret); | |||
69 | if (r < 0) | |||
70 | return log_error_errno(r, "Cannot normalize specified image path '%s': %m", image)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 70, __func__, "Cannot normalize specified image path '%s': %m" , image) : -abs(_e); }); | |||
71 | ||||
72 | return 0; | |||
73 | } | |||
74 | ||||
75 | static int extract_prefix(const char *path, char **ret) { | |||
76 | _cleanup_free___attribute__((cleanup(freep))) char *name = NULL((void*)0); | |||
77 | const char *bn, *underscore; | |||
78 | size_t m; | |||
79 | ||||
80 | bn = basename(path); | |||
81 | ||||
82 | underscore = strchr(bn, '_'); | |||
83 | if (underscore) | |||
84 | m = underscore - bn; | |||
85 | else { | |||
86 | const char *e; | |||
87 | ||||
88 | e = endswith(bn, ".raw"); | |||
89 | if (!e) | |||
90 | e = strchr(bn, 0); | |||
91 | ||||
92 | m = e - bn; | |||
93 | } | |||
94 | ||||
95 | name = strndup(bn, m); | |||
96 | if (!name) | |||
97 | return -ENOMEM12; | |||
98 | ||||
99 | /* A slightly reduced version of what's permitted in unit names. With ':' and '\' are removed, as well as '_' | |||
100 | * which we use as delimiter for the second part of the image string, which we ignore for now. */ | |||
101 | if (!in_charset(name, DIGITS"0123456789" LETTERS"abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "-.")) | |||
102 | return -EINVAL22; | |||
103 | ||||
104 | if (!filename_is_valid(name)) | |||
105 | return -EINVAL22; | |||
106 | ||||
107 | *ret = TAKE_PTR(name)({ typeof(name) _ptr_ = (name); (name) = ((void*)0); _ptr_; } ); | |||
108 | ||||
109 | return 0; | |||
110 | } | |||
111 | ||||
112 | static int determine_matches(const char *image, char **l, bool_Bool allow_any, char ***ret) { | |||
113 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **k = NULL((void*)0); | |||
114 | int r; | |||
115 | ||||
116 | /* Determine the matches to apply. If the list is empty we derive the match from the image name. If the list | |||
117 | * contains exactly the "-" we return a wildcard list (which is the empty list), but only if this is expressly | |||
118 | * permitted. */ | |||
119 | ||||
120 | if (strv_isempty(l)) { | |||
121 | char *prefix; | |||
122 | ||||
123 | r = extract_prefix(image, &prefix); | |||
124 | if (r < 0) | |||
125 | return log_error_errno(r, "Failed to extract prefix of image name '%s': %m", image)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 125, __func__, "Failed to extract prefix of image name '%s': %m" , image) : -abs(_e); }); | |||
126 | ||||
127 | if (!arg_quiet) | |||
128 | log_info("(Matching unit files with prefix '%s'.)", prefix)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 128, __func__, "(Matching unit files with prefix '%s'.)" , prefix) : -abs(_e); }); | |||
129 | ||||
130 | r = strv_consume(&k, prefix); | |||
131 | if (r < 0) | |||
132 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/portable/portablectl.c" , 132, __func__); | |||
133 | ||||
134 | } else if (strv_equal(l, STRV_MAKE("-")((char**) ((const char*[]) { "-", ((void*)0) })))) { | |||
135 | ||||
136 | if (!allow_any) { | |||
137 | log_error("Refusing all unit file match.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 137, __func__, "Refusing all unit file match." ) : -abs(_e); }); | |||
138 | return -EINVAL22; | |||
139 | } | |||
140 | ||||
141 | if (!arg_quiet) | |||
142 | log_info("(Matching all unit files.)")({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 142, __func__, "(Matching all unit files.)" ) : -abs(_e); }); | |||
143 | } else { | |||
144 | ||||
145 | k = strv_copy(l); | |||
146 | if (!k) | |||
147 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/portable/portablectl.c" , 147, __func__); | |||
148 | ||||
149 | if (!arg_quiet) { | |||
150 | _cleanup_free___attribute__((cleanup(freep))) char *joined = NULL((void*)0); | |||
151 | ||||
152 | joined = strv_join(k, "', '"); | |||
153 | if (!joined) | |||
154 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/portable/portablectl.c" , 154, __func__); | |||
155 | ||||
156 | log_info("(Matching unit files with prefixes '%s'.)", joined)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 156, __func__, "(Matching unit files with prefixes '%s'.)" , joined) : -abs(_e); }); | |||
157 | } | |||
158 | } | |||
159 | ||||
160 | *ret = TAKE_PTR(k)({ typeof(k) _ptr_ = (k); (k) = ((void*)0); _ptr_; }); | |||
161 | ||||
162 | return 0; | |||
163 | } | |||
164 | ||||
165 | static int acquire_bus(sd_bus **bus) { | |||
166 | int r; | |||
167 | ||||
168 | assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("bus"), "../src/portable/portablectl.c", 168, __PRETTY_FUNCTION__); } while (0); | |||
169 | ||||
170 | if (*bus) | |||
171 | return 0; | |||
172 | ||||
173 | r = bus_connect_transport(arg_transport, arg_host, false0, bus); | |||
174 | if (r < 0) | |||
175 | return log_error_errno(r, "Failed to connect to bus: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 175, __func__, "Failed to connect to bus: %m" ) : -abs(_e); }); | |||
176 | ||||
177 | (void) sd_bus_set_allow_interactive_authorization(*bus, arg_ask_password); | |||
178 | ||||
179 | return 0; | |||
180 | } | |||
181 | ||||
182 | static int maybe_reload(sd_bus **bus) { | |||
183 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
184 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *m = NULL((void*)0); | |||
185 | int r; | |||
186 | ||||
187 | if (!arg_reload) | |||
188 | return 0; | |||
189 | ||||
190 | r = acquire_bus(bus); | |||
191 | if (r < 0) | |||
192 | return r; | |||
193 | ||||
194 | r = sd_bus_message_new_method_call( | |||
195 | *bus, | |||
196 | &m, | |||
197 | "org.freedesktop.systemd1", | |||
198 | "/org/freedesktop/systemd1", | |||
199 | "org.freedesktop.systemd1.Manager", | |||
200 | "Reload"); | |||
201 | if (r < 0) | |||
202 | return bus_log_create_error(r); | |||
203 | ||||
204 | /* Reloading the daemon may take long, hence set a longer timeout here */ | |||
205 | r = sd_bus_call(*bus, m, DEFAULT_TIMEOUT_USEC(90*((usec_t) 1000000ULL)) * 2, &error, NULL((void*)0)); | |||
206 | if (r < 0) | |||
207 | return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 207, __func__, "Failed to reload daemon: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
208 | ||||
209 | return 0; | |||
210 | } | |||
211 | ||||
212 | static int inspect_image(int argc, char *argv[], void *userdata) { | |||
213 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *m = NULL((void*)0), *reply = NULL((void*)0); | |||
214 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
215 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
216 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **matches = NULL((void*)0); | |||
217 | _cleanup_free___attribute__((cleanup(freep))) char *image = NULL((void*)0); | |||
218 | bool_Bool nl = false0, header = false0; | |||
219 | const void *data; | |||
220 | const char *path; | |||
221 | size_t sz; | |||
222 | int r; | |||
223 | ||||
224 | r = determine_image(argv[1], false0, &image); | |||
225 | if (r < 0) | |||
226 | return r; | |||
227 | ||||
228 | r = determine_matches(argv[1], argv + 2, true1, &matches); | |||
229 | if (r < 0) | |||
230 | return r; | |||
231 | ||||
232 | r = acquire_bus(&bus); | |||
233 | if (r < 0) | |||
234 | return r; | |||
235 | ||||
236 | r = sd_bus_message_new_method_call( | |||
237 | bus, | |||
238 | &m, | |||
239 | "org.freedesktop.portable1", | |||
240 | "/org/freedesktop/portable1", | |||
241 | "org.freedesktop.portable1.Manager", | |||
242 | "GetImageMetadata"); | |||
243 | if (r < 0) | |||
244 | return bus_log_create_error(r); | |||
245 | ||||
246 | r = sd_bus_message_append(m, "s", image); | |||
247 | if (r < 0) | |||
248 | return bus_log_create_error(r); | |||
249 | ||||
250 | r = sd_bus_message_append_strv(m, matches); | |||
251 | if (r < 0) | |||
252 | return bus_log_create_error(r); | |||
253 | ||||
254 | r = sd_bus_call(bus, m, 0, &error, &reply); | |||
255 | if (r < 0) | |||
256 | return log_error_errno(r, "Failed to inspect image metadata: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 256, __func__, "Failed to inspect image metadata: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
257 | ||||
258 | r = sd_bus_message_read(reply, "s", &path); | |||
259 | if (r < 0) | |||
260 | return bus_log_parse_error(r); | |||
261 | ||||
262 | r = sd_bus_message_read_array(reply, 'y', &data, &sz); | |||
263 | if (r < 0) | |||
264 | return bus_log_parse_error(r); | |||
265 | ||||
266 | (void) pager_open(arg_no_pager, false0); | |||
267 | ||||
268 | if (arg_cat) { | |||
269 | printf("%s-- OS Release: --%s\n", ansi_highlight(), ansi_normal()); | |||
270 | fwrite(data, sz, 1, stdoutstdout); | |||
271 | fflush(stdoutstdout); | |||
272 | nl = true1; | |||
273 | } else { | |||
274 | _cleanup_free___attribute__((cleanup(freep))) char *pretty_portable = NULL((void*)0), *pretty_os = NULL((void*)0); | |||
275 | ||||
276 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f; | |||
277 | ||||
278 | f = fmemopen((void*) data, sz, "re"); | |||
279 | if (!f) | |||
280 | return log_error_errno(errno, "Failed to open /etc/os-release buffer: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/portable/portablectl.c", 280, __func__ , "Failed to open /etc/os-release buffer: %m") : -abs(_e); }); | |||
281 | ||||
282 | r = parse_env_file(f, "/etc/os-release", NEWLINE"\n\r", | |||
283 | "PORTABLE_PRETTY_NAME", &pretty_portable, | |||
284 | "PRETTY_NAME", &pretty_os, | |||
285 | NULL((void*)0)); | |||
286 | if (r < 0) | |||
287 | return log_error_errno(r, "Failed to parse /etc/os-release: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 287, __func__, "Failed to parse /etc/os-release: %m" ) : -abs(_e); }); | |||
288 | ||||
289 | printf("Image:\n\t%s\n" | |||
290 | "Portable Service:\n\t%s\n" | |||
291 | "Operating System:\n\t%s\n", | |||
292 | path, | |||
293 | strna(pretty_portable), | |||
294 | strna(pretty_os)); | |||
295 | } | |||
296 | ||||
297 | r = sd_bus_message_enter_container(reply, 'a', "{say}"); | |||
298 | if (r < 0) | |||
299 | return bus_log_parse_error(r); | |||
300 | ||||
301 | for (;;) { | |||
302 | const char *name; | |||
303 | ||||
304 | r = sd_bus_message_enter_container(reply, 'e', "say"); | |||
305 | if (r < 0) | |||
306 | return bus_log_parse_error(r); | |||
307 | if (r == 0) | |||
308 | break; | |||
309 | ||||
310 | r = sd_bus_message_read(reply, "s", &name); | |||
311 | if (r < 0) | |||
312 | return bus_log_parse_error(r); | |||
313 | ||||
314 | r = sd_bus_message_read_array(reply, 'y', &data, &sz); | |||
315 | if (r < 0) | |||
316 | return bus_log_parse_error(r); | |||
317 | ||||
318 | if (arg_cat) { | |||
319 | if (nl) | |||
320 | fputc('\n', stdoutstdout); | |||
321 | ||||
322 | printf("%s-- Unit file: %s --%s\n", ansi_highlight(), name, ansi_normal()); | |||
323 | fwrite(data, sz, 1, stdoutstdout); | |||
324 | fflush(stdoutstdout); | |||
325 | nl = true1; | |||
326 | } else { | |||
327 | if (!header) { | |||
328 | fputs("Unit files:\n", stdoutstdout); | |||
329 | header = true1; | |||
330 | } | |||
331 | ||||
332 | fputc('\t', stdoutstdout); | |||
333 | fputs(name, stdoutstdout); | |||
334 | fputc('\n', stdoutstdout); | |||
335 | } | |||
336 | ||||
337 | r = sd_bus_message_exit_container(reply); | |||
338 | if (r < 0) | |||
339 | return bus_log_parse_error(r); | |||
340 | } | |||
341 | ||||
342 | r = sd_bus_message_exit_container(reply); | |||
343 | if (r < 0) | |||
344 | return bus_log_parse_error(r); | |||
345 | ||||
346 | return 0; | |||
347 | } | |||
348 | ||||
349 | static int print_changes(sd_bus_message *m) { | |||
350 | int r; | |||
351 | ||||
352 | if (arg_quiet) | |||
353 | return 0; | |||
354 | ||||
355 | r = sd_bus_message_enter_container(m, 'a', "(sss)"); | |||
356 | if (r < 0) | |||
357 | return bus_log_parse_error(r); | |||
358 | ||||
359 | for (;;) { | |||
360 | const char *type, *path, *source; | |||
361 | ||||
362 | r = sd_bus_message_read(m, "(sss)", &type, &path, &source); | |||
363 | if (r < 0) | |||
364 | return bus_log_parse_error(r); | |||
365 | if (r == 0) | |||
366 | break; | |||
367 | ||||
368 | if (streq(type, "symlink")(strcmp((type),("symlink")) == 0)) | |||
369 | log_info("Created symlink %s %s %s.", path, special_glyph(ARROW), source)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 369, __func__, "Created symlink %s %s %s." , path, special_glyph(ARROW), source) : -abs(_e); }); | |||
370 | else if (streq(type, "copy")(strcmp((type),("copy")) == 0)) { | |||
371 | if (isempty(source)) | |||
372 | log_info("Copied %s.", path)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 372, __func__, "Copied %s." , path) : -abs(_e); }); | |||
373 | else | |||
374 | log_info("Copied %s %s %s.", source, special_glyph(ARROW), path)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 374, __func__, "Copied %s %s %s." , source, special_glyph(ARROW), path) : -abs(_e); }); | |||
375 | } else if (streq(type, "unlink")(strcmp((type),("unlink")) == 0)) | |||
376 | log_info("Removed %s.", path)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 376, __func__, "Removed %s." , path) : -abs(_e); }); | |||
377 | else if (streq(type, "write")(strcmp((type),("write")) == 0)) | |||
378 | log_info("Written %s.", path)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 378, __func__, "Written %s." , path) : -abs(_e); }); | |||
379 | else if (streq(type, "mkdir")(strcmp((type),("mkdir")) == 0)) | |||
380 | log_info("Created directory %s.", path)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 380, __func__, "Created directory %s." , path) : -abs(_e); }); | |||
381 | else | |||
382 | log_error("Unexpected change: %s/%s/%s", type, path, source)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 382, __func__, "Unexpected change: %s/%s/%s" , type, path, source) : -abs(_e); }); | |||
383 | } | |||
384 | ||||
385 | r = sd_bus_message_exit_container(m); | |||
386 | if (r < 0) | |||
387 | return r; | |||
388 | ||||
389 | return 0; | |||
390 | } | |||
391 | ||||
392 | static int attach_image(int argc, char *argv[], void *userdata) { | |||
393 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *m = NULL((void*)0), *reply = NULL((void*)0); | |||
394 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
395 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
396 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **matches = NULL((void*)0); | |||
397 | _cleanup_free___attribute__((cleanup(freep))) char *image = NULL((void*)0); | |||
398 | int r; | |||
399 | ||||
400 | r = determine_image(argv[1], false0, &image); | |||
401 | if (r < 0) | |||
402 | return r; | |||
403 | ||||
404 | r = determine_matches(argv[1], argv + 2, false0, &matches); | |||
405 | if (r < 0) | |||
406 | return r; | |||
407 | ||||
408 | r = acquire_bus(&bus); | |||
409 | if (r < 0) | |||
410 | return r; | |||
411 | ||||
412 | (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); | |||
413 | ||||
414 | r = sd_bus_message_new_method_call( | |||
415 | bus, | |||
416 | &m, | |||
417 | "org.freedesktop.portable1", | |||
418 | "/org/freedesktop/portable1", | |||
419 | "org.freedesktop.portable1.Manager", | |||
420 | "AttachImage"); | |||
421 | if (r < 0) | |||
422 | return bus_log_create_error(r); | |||
423 | ||||
424 | r = sd_bus_message_append(m, "s", image); | |||
425 | if (r < 0) | |||
426 | return bus_log_create_error(r); | |||
427 | ||||
428 | r = sd_bus_message_append_strv(m, matches); | |||
429 | if (r < 0) | |||
430 | return bus_log_create_error(r); | |||
431 | ||||
432 | r = sd_bus_message_append(m, "sbs", arg_profile, arg_runtime, arg_copy_mode); | |||
433 | if (r < 0) | |||
434 | return bus_log_create_error(r); | |||
435 | ||||
436 | r = sd_bus_call(bus, m, 0, &error, &reply); | |||
437 | if (r < 0) | |||
438 | return log_error_errno(r, "Failed to attach image: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 438, __func__, "Failed to attach image: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
439 | ||||
440 | (void) maybe_reload(&bus); | |||
441 | ||||
442 | print_changes(reply); | |||
443 | return 0; | |||
444 | } | |||
445 | ||||
446 | static int detach_image(int argc, char *argv[], void *userdata) { | |||
447 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *reply = NULL((void*)0); | |||
448 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
449 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
450 | _cleanup_free___attribute__((cleanup(freep))) char *image = NULL((void*)0); | |||
451 | int r; | |||
452 | ||||
453 | r = determine_image(argv[1], true1, &image); | |||
454 | if (r < 0) | |||
455 | return r; | |||
456 | ||||
457 | r = acquire_bus(&bus); | |||
458 | if (r < 0) | |||
459 | return r; | |||
460 | ||||
461 | (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); | |||
462 | ||||
463 | r = sd_bus_call_method( | |||
464 | bus, | |||
465 | "org.freedesktop.portable1", | |||
466 | "/org/freedesktop/portable1", | |||
467 | "org.freedesktop.portable1.Manager", | |||
468 | "DetachImage", | |||
469 | &error, | |||
470 | &reply, | |||
471 | "sb", image, arg_runtime); | |||
472 | if (r < 0) | |||
473 | return log_error_errno(r, "Failed to detach image: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 473, __func__, "Failed to detach image: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
474 | ||||
475 | (void) maybe_reload(&bus); | |||
476 | ||||
477 | print_changes(reply); | |||
478 | return 0; | |||
479 | } | |||
480 | ||||
481 | static int list_images(int argc, char *argv[], void *userdata) { | |||
482 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
483 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *reply = NULL((void*)0); | |||
484 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
485 | _cleanup_(table_unrefp)__attribute__((cleanup(table_unrefp))) Table *table = NULL((void*)0); | |||
486 | int r; | |||
487 | ||||
488 | r = acquire_bus(&bus); | |||
489 | if (r < 0) | |||
490 | return r; | |||
491 | ||||
492 | r = sd_bus_call_method( | |||
493 | bus, | |||
494 | "org.freedesktop.portable1", | |||
495 | "/org/freedesktop/portable1", | |||
496 | "org.freedesktop.portable1.Manager", | |||
497 | "ListImages", | |||
498 | &error, | |||
499 | &reply, | |||
500 | NULL((void*)0)); | |||
501 | if (r < 0) | |||
502 | return log_error_errno(r, "Failed to list images: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 502, __func__, "Failed to list images: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
503 | ||||
504 | table = table_new("NAME", "TYPE", "RO", "CRTIME", "MTIME", "USAGE", "STATE")table_new_internal("NAME", "TYPE", "RO", "CRTIME", "MTIME", "USAGE" , "STATE", ((void*)0)); | |||
505 | if (!table) | |||
506 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/portable/portablectl.c" , 506, __func__); | |||
507 | ||||
508 | r = sd_bus_message_enter_container(reply, 'a', "(ssbtttso)"); | |||
509 | if (r < 0) | |||
510 | return bus_log_parse_error(r); | |||
511 | ||||
512 | for (;;) { | |||
513 | const char *name, *type, *state; | |||
514 | uint64_t crtime, mtime, usage; | |||
515 | TableCell *cell; | |||
516 | bool_Bool ro_bool; | |||
517 | int ro_int; | |||
518 | ||||
519 | r = sd_bus_message_read(reply, "(ssbtttso)", &name, &type, &ro_int, &crtime, &mtime, &usage, &state, NULL((void*)0)); | |||
520 | if (r < 0) | |||
521 | return bus_log_parse_error(r); | |||
522 | if (r == 0) | |||
523 | break; | |||
524 | ||||
525 | r = table_add_many(table,table_add_many_internal(table, TABLE_STRING, name, TABLE_STRING , type, _TABLE_DATA_TYPE_MAX) | |||
526 | TABLE_STRING, name,table_add_many_internal(table, TABLE_STRING, name, TABLE_STRING , type, _TABLE_DATA_TYPE_MAX) | |||
527 | TABLE_STRING, type)table_add_many_internal(table, TABLE_STRING, name, TABLE_STRING , type, _TABLE_DATA_TYPE_MAX); | |||
528 | if (r < 0) | |||
529 | return log_error_errno(r, "Failed to add row to table: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 529, __func__, "Failed to add row to table: %m" ) : -abs(_e); }); | |||
530 | ||||
531 | ro_bool = ro_int; | |||
532 | r = table_add_cell(table, &cell, TABLE_BOOLEAN, &ro_bool); | |||
533 | if (r < 0) | |||
534 | return log_error_errno(r, "Failed to add row to table: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 534, __func__, "Failed to add row to table: %m" ) : -abs(_e); }); | |||
535 | ||||
536 | if (ro_bool) { | |||
537 | r = table_set_color(table, cell, ansi_highlight_red()); | |||
538 | if (r < 0) | |||
539 | return log_error_errno(r, "Failed to set table cell color: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 539, __func__, "Failed to set table cell color: %m" ) : -abs(_e); }); | |||
540 | } | |||
541 | ||||
542 | r = table_add_many(table,table_add_many_internal(table, TABLE_TIMESTAMP, crtime, TABLE_TIMESTAMP , mtime, TABLE_SIZE, usage, _TABLE_DATA_TYPE_MAX) | |||
543 | TABLE_TIMESTAMP, crtime,table_add_many_internal(table, TABLE_TIMESTAMP, crtime, TABLE_TIMESTAMP , mtime, TABLE_SIZE, usage, _TABLE_DATA_TYPE_MAX) | |||
544 | TABLE_TIMESTAMP, mtime,table_add_many_internal(table, TABLE_TIMESTAMP, crtime, TABLE_TIMESTAMP , mtime, TABLE_SIZE, usage, _TABLE_DATA_TYPE_MAX) | |||
545 | TABLE_SIZE, usage)table_add_many_internal(table, TABLE_TIMESTAMP, crtime, TABLE_TIMESTAMP , mtime, TABLE_SIZE, usage, _TABLE_DATA_TYPE_MAX); | |||
546 | if (r < 0) | |||
547 | return log_error_errno(r, "Failed to add row to table: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 547, __func__, "Failed to add row to table: %m" ) : -abs(_e); }); | |||
548 | ||||
549 | r = table_add_cell(table, &cell, TABLE_STRING, state); | |||
550 | if (r < 0) | |||
551 | return log_error_errno(r, "Failed to add row to table: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 551, __func__, "Failed to add row to table: %m" ) : -abs(_e); }); | |||
552 | ||||
553 | if (!streq(state, "detached")(strcmp((state),("detached")) == 0)) { | |||
554 | r = table_set_color(table, cell, ansi_highlight_green()); | |||
555 | if (r < 0) | |||
556 | return log_error_errno(r, "Failed to set table cell color: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 556, __func__, "Failed to set table cell color: %m" ) : -abs(_e); }); | |||
557 | } | |||
558 | } | |||
559 | ||||
560 | r = sd_bus_message_exit_container(reply); | |||
561 | if (r < 0) | |||
562 | return bus_log_parse_error(r); | |||
563 | ||||
564 | if (table_get_rows(table) > 1) { | |||
565 | r = table_set_sort(table, (size_t) 0, (size_t) -1); | |||
566 | if (r < 0) | |||
567 | return log_error_errno(r, "Failed to sort table: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 567, __func__, "Failed to sort table: %m" ) : -abs(_e); }); | |||
568 | ||||
569 | table_set_header(table, arg_legend); | |||
570 | ||||
571 | r = table_print(table, NULL((void*)0)); | |||
572 | if (r < 0) | |||
573 | return log_error_errno(r, "Failed to show table: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 573, __func__, "Failed to show table: %m" ) : -abs(_e); }); | |||
574 | } | |||
575 | ||||
576 | if (arg_legend) { | |||
577 | if (table_get_rows(table) > 1) | |||
578 | printf("\n%zu images listed.\n", table_get_rows(table) - 1); | |||
579 | else | |||
580 | printf("No images.\n"); | |||
581 | } | |||
582 | ||||
583 | return 0; | |||
584 | } | |||
585 | ||||
586 | static int remove_image(int argc, char *argv[], void *userdata) { | |||
587 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
588 | int r, i; | |||
589 | ||||
590 | r = acquire_bus(&bus); | |||
591 | if (r < 0) | |||
592 | return r; | |||
593 | ||||
594 | (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); | |||
595 | ||||
596 | for (i = 1; i < argc; i++) { | |||
597 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
598 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *m = NULL((void*)0); | |||
599 | ||||
600 | r = sd_bus_message_new_method_call( | |||
601 | bus, | |||
602 | &m, | |||
603 | "org.freedesktop.portable1", | |||
604 | "/org/freedesktop/portable1", | |||
605 | "org.freedesktop.portable1.Manager", | |||
606 | "RemoveImage"); | |||
607 | if (r < 0) | |||
608 | return bus_log_create_error(r); | |||
609 | ||||
610 | r = sd_bus_message_append(m, "s", argv[i]); | |||
611 | if (r < 0) | |||
612 | return bus_log_create_error(r); | |||
613 | ||||
614 | /* This is a slow operation, hence turn off any method call timeouts */ | |||
615 | r = sd_bus_call(bus, m, USEC_INFINITY((usec_t) -1), &error, NULL((void*)0)); | |||
616 | if (r < 0) | |||
617 | return log_error_errno(r, "Could not remove image: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 617, __func__, "Could not remove image: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
618 | } | |||
619 | ||||
620 | return 0; | |||
621 | } | |||
622 | ||||
623 | static int read_only_image(int argc, char *argv[], void *userdata) { | |||
624 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
625 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
626 | int b = true1, r; | |||
627 | ||||
628 | if (argc > 2) { | |||
629 | b = parse_boolean(argv[2]); | |||
630 | if (b < 0) | |||
631 | return log_error_errno(b, "Failed to parse boolean argument: %s", argv[2])({ int _level = ((3)), _e = ((b)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 631, __func__, "Failed to parse boolean argument: %s" , argv[2]) : -abs(_e); }); | |||
632 | } | |||
633 | ||||
634 | r = acquire_bus(&bus); | |||
635 | if (r < 0) | |||
636 | return r; | |||
637 | ||||
638 | (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); | |||
639 | ||||
640 | r = sd_bus_call_method( | |||
641 | bus, | |||
642 | "org.freedesktop.portable1", | |||
643 | "/org/freedesktop/portable1", | |||
644 | "org.freedesktop.portable1.Manager", | |||
645 | "MarkImageReadOnly", | |||
646 | &error, | |||
647 | NULL((void*)0), | |||
648 | "sb", argv[1], b); | |||
649 | if (r < 0) | |||
650 | return log_error_errno(r, "Could not mark image read-only: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 650, __func__, "Could not mark image read-only: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
651 | ||||
652 | return 0; | |||
653 | } | |||
654 | ||||
655 | static int set_limit(int argc, char *argv[], void *userdata) { | |||
656 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
657 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
658 | uint64_t limit; | |||
659 | int r; | |||
660 | ||||
661 | r = acquire_bus(&bus); | |||
662 | if (r < 0) | |||
663 | return r; | |||
664 | ||||
665 | (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); | |||
666 | ||||
667 | if (STR_IN_SET(argv[argc-1], "-", "none", "infinity")(!!strv_find((((char**) ((const char*[]) { "-", "none", "infinity" , ((void*)0) }))), (argv[argc-1])))) | |||
668 | limit = (uint64_t) -1; | |||
669 | else { | |||
670 | r = parse_size(argv[argc-1], 1024, &limit); | |||
671 | if (r < 0) | |||
672 | return log_error_errno(r, "Failed to parse size: %s", argv[argc-1])({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 672, __func__, "Failed to parse size: %s" , argv[argc-1]) : -abs(_e); }); | |||
673 | } | |||
674 | ||||
675 | if (argc > 2) | |||
676 | /* With two arguments changes the quota limit of the specified image */ | |||
677 | r = sd_bus_call_method( | |||
678 | bus, | |||
679 | "org.freedesktop.portable1", | |||
680 | "/org/freedesktop/portable1", | |||
681 | "org.freedesktop.portable1.Manager", | |||
682 | "SetImageLimit", | |||
683 | &error, | |||
684 | NULL((void*)0), | |||
685 | "st", argv[1], limit); | |||
686 | else | |||
687 | /* With one argument changes the pool quota limit */ | |||
688 | r = sd_bus_call_method( | |||
689 | bus, | |||
690 | "org.freedesktop.portable1", | |||
691 | "/org/freedesktop/portable1", | |||
692 | "org.freedesktop.portable1.Manager", | |||
693 | "SetPoolLimit", | |||
694 | &error, | |||
695 | NULL((void*)0), | |||
696 | "t", limit); | |||
697 | ||||
698 | if (r < 0) | |||
699 | return log_error_errno(r, "Could not set limit: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 699, __func__, "Could not set limit: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
700 | ||||
701 | return 0; | |||
702 | } | |||
703 | ||||
704 | static int is_image_attached(int argc, char *argv[], void *userdata) { | |||
705 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *reply = NULL((void*)0); | |||
706 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
707 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
708 | _cleanup_free___attribute__((cleanup(freep))) char *image = NULL((void*)0); | |||
709 | const char *state; | |||
710 | int r; | |||
711 | ||||
712 | r = determine_image(argv[1], true1, &image); | |||
| ||||
713 | if (r
| |||
714 | return r; | |||
715 | ||||
716 | r = acquire_bus(&bus); | |||
717 | if (r < 0) | |||
718 | return r; | |||
| ||||
719 | ||||
720 | r = sd_bus_call_method( | |||
721 | bus, | |||
722 | "org.freedesktop.portable1", | |||
723 | "/org/freedesktop/portable1", | |||
724 | "org.freedesktop.portable1.Manager", | |||
725 | "GetImageState", | |||
726 | &error, | |||
727 | &reply, | |||
728 | "s", image); | |||
729 | if (r < 0) | |||
730 | return log_error_errno(r, "Failed to get image state: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 730, __func__, "Failed to get image state: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
731 | ||||
732 | r = sd_bus_message_read(reply, "s", &state); | |||
733 | if (r < 0) | |||
734 | return r; | |||
735 | ||||
736 | if (!arg_quiet) | |||
737 | puts(state); | |||
738 | ||||
739 | return streq(state, "detached")(strcmp((state),("detached")) == 0); | |||
740 | } | |||
741 | ||||
742 | static int dump_profiles(void) { | |||
743 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
744 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
745 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **l = NULL((void*)0); | |||
746 | char **i; | |||
747 | int r; | |||
748 | ||||
749 | r = acquire_bus(&bus); | |||
750 | if (r < 0) | |||
751 | return r; | |||
752 | ||||
753 | r = sd_bus_get_property_strv( | |||
754 | bus, | |||
755 | "org.freedesktop.portable1", | |||
756 | "/org/freedesktop/portable1", | |||
757 | "org.freedesktop.portable1.Manager", | |||
758 | "Profiles", | |||
759 | &error, | |||
760 | &l); | |||
761 | if (r < 0) | |||
762 | return log_error_errno(r, "Failed to acquire list of profiles: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 762, __func__, "Failed to acquire list of profiles: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
763 | ||||
764 | if (arg_legend) | |||
765 | log_info("Available unit profiles:")({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 765, __func__, "Available unit profiles:" ) : -abs(_e); }); | |||
766 | ||||
767 | STRV_FOREACH(i, l)for ((i) = (l); (i) && *(i); (i)++) { | |||
768 | fputs(*i, stdoutstdout); | |||
769 | fputc('\n', stdoutstdout); | |||
770 | } | |||
771 | ||||
772 | return 0; | |||
773 | } | |||
774 | ||||
775 | static int help(int argc, char *argv[], void *userdata) { | |||
776 | ||||
777 | (void) pager_open(arg_no_pager, false0); | |||
778 | ||||
779 | printf("%s [OPTIONS...] {COMMAND} ...\n\n" | |||
780 | "Attach or detach portable services from the local system.\n\n" | |||
781 | " -h --help Show this help\n" | |||
782 | " --version Show package version\n" | |||
783 | " --no-pager Do not pipe output into a pager\n" | |||
784 | " --no-legend Do not show the headers and footers\n" | |||
785 | " --no-ask-password Do not ask for system passwords\n" | |||
786 | " -H --host=[USER@]HOST Operate on remote host\n" | |||
787 | " -M --machine=CONTAINER Operate on local container\n" | |||
788 | " -q --quiet Suppress informational messages\n" | |||
789 | " -p --profile=PROFILE Pick security profile for portable service\n" | |||
790 | " --copy=copy|auto|symlink Prefer copying or symlinks if possible\n" | |||
791 | " --runtime Attach portable service until next reboot only\n" | |||
792 | " --no-reload Don't reload the system and service manager\n" | |||
793 | " --cat When inspecting include unit and os-release file\n" | |||
794 | " contents\n\n" | |||
795 | "Commands:\n" | |||
796 | " list List available portable service images\n" | |||
797 | " attach NAME|PATH [PREFIX...]\n" | |||
798 | " Attach the specified portable service image\n" | |||
799 | " detach NAME|PATH Detach the specified portable service image\n" | |||
800 | " inspect NAME|PATH [PREFIX...]\n" | |||
801 | " Show details of specified portable service image\n" | |||
802 | " is-attached NAME|PATH Query if portable service image is attached\n" | |||
803 | " read-only NAME|PATH [BOOL] Mark or unmark portable service image read-only\n" | |||
804 | " remove NAME|PATH... Remove a portable service image\n" | |||
805 | " set-limit [NAME|PATH] Set image or pool size limit (disk quota)\n" | |||
806 | , program_invocation_short_name); | |||
807 | ||||
808 | return 0; | |||
809 | } | |||
810 | ||||
811 | static int parse_argv(int argc, char *argv[]) { | |||
812 | ||||
813 | enum { | |||
814 | ARG_VERSION = 0x100, | |||
815 | ARG_NO_PAGER, | |||
816 | ARG_NO_LEGEND, | |||
817 | ARG_NO_ASK_PASSWORD, | |||
818 | ARG_COPY, | |||
819 | ARG_RUNTIME, | |||
820 | ARG_NO_RELOAD, | |||
821 | ARG_CAT, | |||
822 | }; | |||
823 | ||||
824 | static const struct option options[] = { | |||
825 | { "help", no_argument0, NULL((void*)0), 'h' }, | |||
826 | { "version", no_argument0, NULL((void*)0), ARG_VERSION }, | |||
827 | { "no-pager", no_argument0, NULL((void*)0), ARG_NO_PAGER }, | |||
828 | { "no-legend", no_argument0, NULL((void*)0), ARG_NO_LEGEND }, | |||
829 | { "no-ask-password", no_argument0, NULL((void*)0), ARG_NO_ASK_PASSWORD }, | |||
830 | { "host", required_argument1, NULL((void*)0), 'H' }, | |||
831 | { "machine", required_argument1, NULL((void*)0), 'M' }, | |||
832 | { "quiet", no_argument0, NULL((void*)0), 'q' }, | |||
833 | { "profile", required_argument1, NULL((void*)0), 'p' }, | |||
834 | { "copy", required_argument1, NULL((void*)0), ARG_COPY }, | |||
835 | { "runtime", no_argument0, NULL((void*)0), ARG_RUNTIME }, | |||
836 | { "no-reload", no_argument0, NULL((void*)0), ARG_NO_RELOAD }, | |||
837 | { "cat", no_argument0, NULL((void*)0), ARG_CAT }, | |||
838 | {} | |||
839 | }; | |||
840 | ||||
841 | assert(argc >= 0)do { if ((__builtin_expect(!!(!(argc >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("argc >= 0"), "../src/portable/portablectl.c" , 841, __PRETTY_FUNCTION__); } while (0); | |||
842 | assert(argv)do { if ((__builtin_expect(!!(!(argv)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("argv"), "../src/portable/portablectl.c" , 842, __PRETTY_FUNCTION__); } while (0); | |||
843 | ||||
844 | for (;;) { | |||
845 | int c; | |||
846 | ||||
847 | c = getopt_long(argc, argv, "hH:M:qp:", options, NULL((void*)0)); | |||
848 | if (c < 0) | |||
849 | break; | |||
850 | ||||
851 | switch (c) { | |||
852 | ||||
853 | case 'h': | |||
854 | help(0, NULL((void*)0), NULL((void*)0)); | |||
855 | return 0; | |||
856 | ||||
857 | case ARG_VERSION: | |||
858 | return version(); | |||
859 | ||||
860 | case ARG_NO_PAGER: | |||
861 | arg_no_pager = true1; | |||
862 | break; | |||
863 | ||||
864 | case ARG_NO_LEGEND: | |||
865 | arg_legend = false0; | |||
866 | break; | |||
867 | ||||
868 | case ARG_NO_ASK_PASSWORD: | |||
869 | arg_ask_password = false0; | |||
870 | break; | |||
871 | ||||
872 | case 'H': | |||
873 | arg_transport = BUS_TRANSPORT_REMOTE; | |||
874 | arg_host = optarg; | |||
875 | break; | |||
876 | ||||
877 | case 'M': | |||
878 | arg_transport = BUS_TRANSPORT_MACHINE; | |||
879 | arg_host = optarg; | |||
880 | break; | |||
881 | ||||
882 | case 'q': | |||
883 | arg_quiet = true1; | |||
884 | break; | |||
885 | ||||
886 | case 'p': | |||
887 | if (streq(optarg, "help")(strcmp((optarg),("help")) == 0)) | |||
888 | return dump_profiles(); | |||
889 | ||||
890 | if (!filename_is_valid(optarg)) { | |||
891 | log_error("Unit profile name not valid: %s", optarg)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 891, __func__, "Unit profile name not valid: %s" , optarg) : -abs(_e); }); | |||
892 | return -EINVAL22; | |||
893 | } | |||
894 | ||||
895 | arg_profile = optarg; | |||
896 | break; | |||
897 | ||||
898 | case ARG_COPY: | |||
899 | if (streq(optarg, "auto")(strcmp((optarg),("auto")) == 0)) | |||
900 | arg_copy_mode = NULL((void*)0); | |||
901 | else if (STR_IN_SET(optarg, "copy", "symlink")(!!strv_find((((char**) ((const char*[]) { "copy", "symlink", ((void*)0) }))), (optarg)))) | |||
902 | arg_copy_mode = optarg; | |||
903 | else if (streq(optarg, "help")(strcmp((optarg),("help")) == 0)) { | |||
904 | puts("auto\n" | |||
905 | "copy\n" | |||
906 | "symlink"); | |||
907 | return 0; | |||
908 | } else { | |||
909 | log_error("Failed to parse --copy= argument: %s", optarg)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/portable/portablectl.c", 909, __func__, "Failed to parse --copy= argument: %s" , optarg) : -abs(_e); }); | |||
910 | return -EINVAL22; | |||
911 | } | |||
912 | ||||
913 | break; | |||
914 | ||||
915 | case ARG_RUNTIME: | |||
916 | arg_runtime = true1; | |||
917 | break; | |||
918 | ||||
919 | case ARG_NO_RELOAD: | |||
920 | arg_reload = false0; | |||
921 | break; | |||
922 | ||||
923 | case ARG_CAT: | |||
924 | arg_cat = true1; | |||
925 | break; | |||
926 | ||||
927 | case '?': | |||
928 | return -EINVAL22; | |||
929 | ||||
930 | default: | |||
931 | assert_not_reached("Unhandled option")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unhandled option"), "../src/portable/portablectl.c", 931, __PRETTY_FUNCTION__ ); } while (0); | |||
932 | } | |||
933 | } | |||
934 | ||||
935 | return 1; | |||
936 | } | |||
937 | ||||
938 | int main(int argc, char *argv[]) { | |||
939 | ||||
940 | static const Verb verbs[] = { | |||
941 | { "help", VERB_ANY((unsigned) -1), VERB_ANY((unsigned) -1), 0, help }, | |||
942 | { "list", VERB_ANY((unsigned) -1), 1, VERB_DEFAULT, list_images }, | |||
943 | { "attach", 2, VERB_ANY((unsigned) -1), 0, attach_image }, | |||
944 | { "detach", 2, 2, 0, detach_image }, | |||
945 | { "inspect", 2, VERB_ANY((unsigned) -1), 0, inspect_image }, | |||
946 | { "is-attached", 2, 2, 0, is_image_attached }, | |||
947 | { "read-only", 2, 3, 0, read_only_image }, | |||
948 | { "remove", 2, VERB_ANY((unsigned) -1), 0, remove_image }, | |||
949 | { "set-limit", 3, 3, 0, set_limit }, | |||
950 | {} | |||
951 | }; | |||
952 | ||||
953 | int r; | |||
954 | ||||
955 | log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD); | |||
956 | log_open(); | |||
957 | ||||
958 | r = parse_argv(argc, argv); | |||
959 | if (r <= 0) | |||
960 | goto finish; | |||
961 | ||||
962 | r = dispatch_verb(argc, argv, verbs, NULL((void*)0)); | |||
963 | ||||
964 | finish: | |||
965 | pager_close(); | |||
966 | ||||
967 | return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0; | |||
968 | } |