Bug Summary

File:build-scan/../src/portable/portablectl.c
Warning:line 102, column 25
Potential leak of memory pointed to by 'name'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name portablectl.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I portablectl.p -I . -I .. -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/portable/portablectl.c
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
28static bool_Bool arg_no_pager = false0;
29static bool_Bool arg_legend = true1;
30static bool_Bool arg_ask_password = true1;
31static bool_Bool arg_quiet = false0;
32static const char *arg_profile = "default";
33static const char* arg_copy_mode = NULL((void*)0);
34static bool_Bool arg_runtime = false0;
35static bool_Bool arg_reload = true1;
36static bool_Bool arg_cat = false0;
37static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
38static char *arg_host = NULL((void*)0);
39
40static 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
75static 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)
6
Assuming 'underscore' is non-null
7
Taking true branch
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);
8
Memory is allocated
96 if (!name)
9
Assuming 'name' is non-null
10
Taking false branch
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" "-."))
11
Assuming the condition is true
12
Taking true branch
102 return -EINVAL22;
13
Potential leak of memory pointed to by 'name'
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
112static 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)) {
4
Taking true branch
121 char *prefix;
122
123 r = extract_prefix(image, &prefix);
5
Calling 'extract_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
165static 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
182static 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
212static 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
349static 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
392static 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)
1
Assuming 'r' is >= 0
2
Taking false branch
402 return r;
403
404 r = determine_matches(argv[1], argv + 2, false0, &matches);
3
Calling 'determine_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
446static 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
481static 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
586static 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
623static 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
655static 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
704static 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 < 0)
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
742static 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
775static 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
811static 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
938int 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
964finish:
965 pager_close();
966
967 return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0;
968}