]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/import/importd.c
shared: split out property get helpers
[thirdparty/systemd.git] / src / import / importd.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
3d7415f4
LP
2
3#include <sys/prctl.h>
d7e454ba 4#include <sys/wait.h>
3d7415f4
LP
5
6#include "sd-bus.h"
3ffd4af2 7
b5efdb8a 8#include "alloc-util.h"
3d7415f4 9#include "bus-common-errors.h"
40af3d02 10#include "bus-get-properties.h"
ac9f55ed 11#include "bus-log-control-api.h"
269e4d2d 12#include "bus-polkit.h"
a97dcc12 13#include "def.h"
3ffd4af2 14#include "fd-util.h"
1d7579c4 15#include "float.h"
3ffd4af2
LP
16#include "hostname-util.h"
17#include "import-util.h"
432cea00 18#include "machine-pool.h"
5e332028 19#include "main-func.h"
f5947a5e 20#include "missing_capability.h"
3ffd4af2 21#include "mkdir.h"
6bedfcbb 22#include "parse-util.h"
113b3fc1 23#include "path-util.h"
0b452006 24#include "process-util.h"
fc021a5b 25#include "service-util.h"
40af3d02 26#include "signal-util.h"
3ffd4af2 27#include "socket-util.h"
176a05c2 28#include "stat-util.h"
8b43440b 29#include "string-table.h"
3ffd4af2 30#include "strv.h"
7ccbd1ae 31#include "syslog-util.h"
ee104e11 32#include "user-util.h"
3ffd4af2 33#include "util.h"
49cf4170 34#include "web-util.h"
3d7415f4
LP
35
36typedef struct Transfer Transfer;
37typedef struct Manager Manager;
38
39typedef enum TransferType {
b6e676ce
LP
40 TRANSFER_IMPORT_TAR,
41 TRANSFER_IMPORT_RAW,
1d7579c4 42 TRANSFER_IMPORT_FS,
587fec42
LP
43 TRANSFER_EXPORT_TAR,
44 TRANSFER_EXPORT_RAW,
b6e676ce
LP
45 TRANSFER_PULL_TAR,
46 TRANSFER_PULL_RAW,
3d7415f4
LP
47 _TRANSFER_TYPE_MAX,
48 _TRANSFER_TYPE_INVALID = -1,
49} TransferType;
50
51struct Transfer {
52 Manager *manager;
53
54 uint32_t id;
55 char *object_path;
56
57 TransferType type;
58 ImportVerify verify;
59
60 char *remote;
61 char *local;
62 bool force_local;
b6e676ce 63 bool read_only;
3d7415f4 64
587fec42 65 char *format;
3d7415f4
LP
66
67 pid_t pid;
68
69 int log_fd;
70
71 char log_message[LINE_MAX];
72 size_t log_message_size;
73
74 sd_event_source *pid_event_source;
75 sd_event_source *log_event_source;
76
77 unsigned n_canceled;
7079cfef 78 unsigned progress_percent;
b6e676ce
LP
79
80 int stdin_fd;
587fec42 81 int stdout_fd;
3d7415f4
LP
82};
83
84struct Manager {
85 sd_event *event;
86 sd_bus *bus;
87
88 uint32_t current_transfer_id;
89 Hashmap *transfers;
90
91 Hashmap *polkit_registry;
7079cfef
LP
92
93 int notify_fd;
94
95 sd_event_source *notify_event_source;
3d7415f4
LP
96};
97
98#define TRANSFERS_MAX 64
99
100static const char* const transfer_type_table[_TRANSFER_TYPE_MAX] = {
b6e676ce
LP
101 [TRANSFER_IMPORT_TAR] = "import-tar",
102 [TRANSFER_IMPORT_RAW] = "import-raw",
1d7579c4 103 [TRANSFER_IMPORT_FS] = "import-fs",
587fec42
LP
104 [TRANSFER_EXPORT_TAR] = "export-tar",
105 [TRANSFER_EXPORT_RAW] = "export-raw",
b6e676ce
LP
106 [TRANSFER_PULL_TAR] = "pull-tar",
107 [TRANSFER_PULL_RAW] = "pull-raw",
3d7415f4
LP
108};
109
b9a5f858 110DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType);
3d7415f4
LP
111
112static Transfer *transfer_unref(Transfer *t) {
113 if (!t)
114 return NULL;
115
116 if (t->manager)
117 hashmap_remove(t->manager->transfers, UINT32_TO_PTR(t->id));
118
119 sd_event_source_unref(t->pid_event_source);
120 sd_event_source_unref(t->log_event_source);
121
122 free(t->remote);
123 free(t->local);
587fec42 124 free(t->format);
3d7415f4
LP
125 free(t->object_path);
126
127 if (t->pid > 0) {
128 (void) kill_and_sigcont(t->pid, SIGKILL);
129 (void) wait_for_terminate(t->pid, NULL);
130 }
131
132 safe_close(t->log_fd);
b6e676ce 133 safe_close(t->stdin_fd);
587fec42 134 safe_close(t->stdout_fd);
3d7415f4 135
6b430fdb 136 return mfree(t);
3d7415f4
LP
137}
138
139DEFINE_TRIVIAL_CLEANUP_FUNC(Transfer*, transfer_unref);
140
141static int transfer_new(Manager *m, Transfer **ret) {
142 _cleanup_(transfer_unrefp) Transfer *t = NULL;
143 uint32_t id;
144 int r;
145
146 assert(m);
147 assert(ret);
148
149 if (hashmap_size(m->transfers) >= TRANSFERS_MAX)
150 return -E2BIG;
151
152 r = hashmap_ensure_allocated(&m->transfers, &trivial_hash_ops);
153 if (r < 0)
154 return r;
155
0d94088e 156 t = new(Transfer, 1);
3d7415f4
LP
157 if (!t)
158 return -ENOMEM;
159
0d94088e
YW
160 *t = (Transfer) {
161 .type = _TRANSFER_TYPE_INVALID,
162 .log_fd = -1,
163 .stdin_fd = -1,
164 .stdout_fd = -1,
165 .verify = _IMPORT_VERIFY_INVALID,
1d7579c4 166 .progress_percent= (unsigned) -1,
0d94088e 167 };
3d7415f4
LP
168
169 id = m->current_transfer_id + 1;
170
171 if (asprintf(&t->object_path, "/org/freedesktop/import1/transfer/_%" PRIu32, id) < 0)
172 return -ENOMEM;
173
174 r = hashmap_put(m->transfers, UINT32_TO_PTR(id), t);
175 if (r < 0)
176 return r;
177
178 m->current_transfer_id = id;
179
180 t->manager = m;
181 t->id = id;
182
1cc6c93a 183 *ret = TAKE_PTR(t);
3d7415f4
LP
184
185 return 0;
186}
187
1d7579c4
LP
188static double transfer_percent_as_double(Transfer *t) {
189 assert(t);
190
191 if (t->progress_percent == (unsigned) -1)
192 return -DBL_MAX;
193
194 return (double) t->progress_percent / 100.0;
195}
196
3d7415f4
LP
197static void transfer_send_log_line(Transfer *t, const char *line) {
198 int r, priority = LOG_INFO;
199
200 assert(t);
201 assert(line);
202
203 syslog_parse_priority(&line, &priority, true);
204
09d46cfd 205 log_full(priority, "(transfer%" PRIu32 ") %s", t->id, line);
3d7415f4
LP
206
207 r = sd_bus_emit_signal(
208 t->manager->bus,
209 t->object_path,
210 "org.freedesktop.import1.Transfer",
211 "LogMessage",
212 "us",
213 priority,
214 line);
215 if (r < 0)
5b6299ee 216 log_warning_errno(r, "Cannot emit log message signal, ignoring: %m");
3d7415f4
LP
217 }
218
219static void transfer_send_logs(Transfer *t, bool flush) {
220 assert(t);
221
222 /* Try to send out all log messages, if we can. But if we
223 * can't we remove the messages from the buffer, but don't
224 * fail */
225
226 while (t->log_message_size > 0) {
227 _cleanup_free_ char *n = NULL;
228 char *e;
229
230 if (t->log_message_size >= sizeof(t->log_message))
231 e = t->log_message + sizeof(t->log_message);
232 else {
233 char *a, *b;
234
235 a = memchr(t->log_message, 0, t->log_message_size);
236 b = memchr(t->log_message, '\n', t->log_message_size);
237
238 if (a && b)
239 e = a < b ? a : b;
240 else if (a)
241 e = a;
242 else
243 e = b;
244 }
245
246 if (!e) {
247 if (!flush)
248 return;
249
250 e = t->log_message + t->log_message_size;
251 }
252
253 n = strndup(t->log_message, e - t->log_message);
254
255 /* Skip over NUL and newlines */
ed0cb346 256 while (e < t->log_message + t->log_message_size && IN_SET(*e, 0, '\n'))
3d7415f4
LP
257 e++;
258
259 memmove(t->log_message, e, t->log_message + sizeof(t->log_message) - e);
260 t->log_message_size -= e - t->log_message;
261
262 if (!n) {
263 log_oom();
264 continue;
265 }
266
267 if (isempty(n))
268 continue;
269
270 transfer_send_log_line(t, n);
271 }
272}
273
274static int transfer_finalize(Transfer *t, bool success) {
275 int r;
276
277 assert(t);
278
279 transfer_send_logs(t, true);
280
281 r = sd_bus_emit_signal(
282 t->manager->bus,
283 "/org/freedesktop/import1",
284 "org.freedesktop.import1.Manager",
285 "TransferRemoved",
286 "uos",
287 t->id,
288 t->object_path,
289 success ? "done" :
290 t->n_canceled > 0 ? "canceled" : "failed");
291
292 if (r < 0)
293 log_error_errno(r, "Cannot emit message: %m");
294
295 transfer_unref(t);
296 return 0;
297}
298
299static int transfer_cancel(Transfer *t) {
300 int r;
301
302 assert(t);
303
304 r = kill_and_sigcont(t->pid, t->n_canceled < 3 ? SIGTERM : SIGKILL);
305 if (r < 0)
306 return r;
307
308 t->n_canceled++;
309 return 0;
310}
311
312static int transfer_on_pid(sd_event_source *s, const siginfo_t *si, void *userdata) {
313 Transfer *t = userdata;
314 bool success = false;
315
316 assert(s);
317 assert(t);
318
319 if (si->si_code == CLD_EXITED) {
320 if (si->si_status != 0)
4b71c27b 321 log_error("Transfer process failed with exit code %i.", si->si_status);
3d7415f4 322 else {
4b71c27b 323 log_debug("Transfer process succeeded.");
3d7415f4
LP
324 success = true;
325 }
326
3742095b 327 } else if (IN_SET(si->si_code, CLD_KILLED, CLD_DUMPED))
4b71c27b 328 log_error("Transfer process terminated by signal %s.", signal_to_string(si->si_status));
3d7415f4 329 else
4b71c27b 330 log_error("Transfer process failed due to unknown reason.");
3d7415f4
LP
331
332 t->pid = 0;
333
334 return transfer_finalize(t, success);
335}
336
337static int transfer_on_log(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
338 Transfer *t = userdata;
339 ssize_t l;
340
341 assert(s);
342 assert(t);
343
344 l = read(fd, t->log_message + t->log_message_size, sizeof(t->log_message) - t->log_message_size);
b0325c99
LP
345 if (l < 0)
346 log_error_errno(errno, "Failed to read log message: %m");
3d7415f4
LP
347 if (l <= 0) {
348 /* EOF/read error. We just close the pipe here, and
349 * close the watch, waiting for the SIGCHLD to arrive,
350 * before we do anything else. */
3d7415f4
LP
351 t->log_event_source = sd_event_source_unref(t->log_event_source);
352 return 0;
353 }
354
355 t->log_message_size += l;
356
357 transfer_send_logs(t, false);
358
359 return 0;
360}
361
362static int transfer_start(Transfer *t) {
363 _cleanup_close_pair_ int pipefd[2] = { -1, -1 };
364 int r;
365
366 assert(t);
367 assert(t->pid <= 0);
368
369 if (pipe2(pipefd, O_CLOEXEC) < 0)
370 return -errno;
371
4c253ed1
LP
372 r = safe_fork("(sd-transfer)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &t->pid);
373 if (r < 0)
374 return r;
375 if (r == 0) {
3d7415f4 376 const char *cmd[] = {
1d7579c4 377 NULL, /* systemd-import, systemd-import-fs, systemd-export or systemd-pull */
b43d75c3 378 NULL, /* tar, raw */
b6e676ce 379 NULL, /* --verify= */
3d7415f4
LP
380 NULL, /* verify argument */
381 NULL, /* maybe --force */
b6e676ce 382 NULL, /* maybe --read-only */
587fec42
LP
383 NULL, /* if so: the actual URL */
384 NULL, /* maybe --format= */
385 NULL, /* if so: the actual format */
3d7415f4
LP
386 NULL, /* remote */
387 NULL, /* local */
388 NULL
389 };
b6e676ce 390 unsigned k = 0;
3d7415f4
LP
391
392 /* Child */
393
3d7415f4
LP
394 pipefd[0] = safe_close(pipefd[0]);
395
2b33ab09
LP
396 r = rearrange_stdio(t->stdin_fd,
397 t->stdout_fd < 0 ? pipefd[1] : t->stdout_fd,
398 pipefd[1]);
399 if (r < 0) {
400 log_error_errno(r, "Failed to set stdin/stdout/stderr: %m");
3d7415f4
LP
401 _exit(EXIT_FAILURE);
402 }
403
df8067ef
ZJS
404 if (setenv("SYSTEMD_LOG_TARGET", "console-prefixed", 1) < 0 ||
405 setenv("NOTIFY_SOCKET", "/run/systemd/import/notify", 1) < 0) {
406 log_error_errno(errno, "setenv() failed: %m");
407 _exit(EXIT_FAILURE);
408 }
3d7415f4 409
1d7579c4
LP
410 switch (t->type) {
411
412 case TRANSFER_IMPORT_TAR:
413 case TRANSFER_IMPORT_RAW:
b6e676ce 414 cmd[k++] = SYSTEMD_IMPORT_PATH;
1d7579c4
LP
415 break;
416
417 case TRANSFER_IMPORT_FS:
418 cmd[k++] = SYSTEMD_IMPORT_FS_PATH;
419 break;
420
421 case TRANSFER_EXPORT_TAR:
422 case TRANSFER_EXPORT_RAW:
587fec42 423 cmd[k++] = SYSTEMD_EXPORT_PATH;
1d7579c4
LP
424 break;
425
426 case TRANSFER_PULL_TAR:
427 case TRANSFER_PULL_RAW:
b6e676ce 428 cmd[k++] = SYSTEMD_PULL_PATH;
1d7579c4
LP
429 break;
430
431 default:
432 assert_not_reached("Unexpected transfer type");
433 }
434
435 switch (t->type) {
b6e676ce 436
1d7579c4
LP
437 case TRANSFER_IMPORT_TAR:
438 case TRANSFER_EXPORT_TAR:
439 case TRANSFER_PULL_TAR:
b6e676ce 440 cmd[k++] = "tar";
1d7579c4
LP
441 break;
442
443 case TRANSFER_IMPORT_RAW:
444 case TRANSFER_EXPORT_RAW:
445 case TRANSFER_PULL_RAW:
b43d75c3 446 cmd[k++] = "raw";
1d7579c4
LP
447 break;
448
449 case TRANSFER_IMPORT_FS:
450 cmd[k++] = "run";
451 break;
452
453 default:
454 break;
455 }
b6e676ce
LP
456
457 if (t->verify != _IMPORT_VERIFY_INVALID) {
458 cmd[k++] = "--verify";
459 cmd[k++] = import_verify_to_string(t->verify);
460 }
461
3d7415f4
LP
462 if (t->force_local)
463 cmd[k++] = "--force";
b6e676ce
LP
464 if (t->read_only)
465 cmd[k++] = "--read-only";
3d7415f4 466
587fec42
LP
467 if (t->format) {
468 cmd[k++] = "--format";
469 cmd[k++] = t->format;
470 }
471
472 if (!IN_SET(t->type, TRANSFER_EXPORT_TAR, TRANSFER_EXPORT_RAW)) {
473 if (t->remote)
474 cmd[k++] = t->remote;
475 else
476 cmd[k++] = "-";
477 }
b6e676ce 478
3d7415f4
LP
479 if (t->local)
480 cmd[k++] = t->local;
481 cmd[k] = NULL;
482
b6e676ce
LP
483 execv(cmd[0], (char * const *) cmd);
484 log_error_errno(errno, "Failed to execute %s tool: %m", cmd[0]);
3d7415f4
LP
485 _exit(EXIT_FAILURE);
486 }
487
488 pipefd[1] = safe_close(pipefd[1]);
c10d6bdb 489 t->log_fd = TAKE_FD(pipefd[0]);
3d7415f4 490
b6e676ce
LP
491 t->stdin_fd = safe_close(t->stdin_fd);
492
ab09bf90
ZJS
493 r = sd_event_add_child(t->manager->event, &t->pid_event_source,
494 t->pid, WEXITED, transfer_on_pid, t);
3d7415f4
LP
495 if (r < 0)
496 return r;
497
ab09bf90
ZJS
498 r = sd_event_add_io(t->manager->event, &t->log_event_source,
499 t->log_fd, EPOLLIN, transfer_on_log, t);
3d7415f4
LP
500 if (r < 0)
501 return r;
502
503 /* Make sure always process logging before SIGCHLD */
504 r = sd_event_source_set_priority(t->log_event_source, SD_EVENT_PRIORITY_NORMAL -5);
505 if (r < 0)
506 return r;
507
508 r = sd_bus_emit_signal(
509 t->manager->bus,
510 "/org/freedesktop/import1",
511 "org.freedesktop.import1.Manager",
512 "TransferNew",
513 "uo",
514 t->id,
515 t->object_path);
516 if (r < 0)
517 return r;
518
519 return 0;
520}
521
522static Manager *manager_unref(Manager *m) {
523 Transfer *t;
524
525 if (!m)
526 return NULL;
527
7079cfef
LP
528 sd_event_source_unref(m->notify_event_source);
529 safe_close(m->notify_fd);
530
3d7415f4
LP
531 while ((t = hashmap_first(m->transfers)))
532 transfer_unref(t);
533
534 hashmap_free(m->transfers);
535
536 bus_verify_polkit_async_registry_free(m->polkit_registry);
537
03976f7b 538 m->bus = sd_bus_flush_close_unref(m->bus);
3d7415f4
LP
539 sd_event_unref(m->event);
540
6b430fdb 541 return mfree(m);
3d7415f4
LP
542}
543
544DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
545
7079cfef
LP
546static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
547
548 char buf[NOTIFY_BUFFER_MAX+1];
549 struct iovec iovec = {
550 .iov_base = buf,
551 .iov_len = sizeof(buf)-1,
552 };
fb29cdbe
LP
553 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) +
554 CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)) control;
7079cfef
LP
555 struct msghdr msghdr = {
556 .msg_iov = &iovec,
557 .msg_iovlen = 1,
558 .msg_control = &control,
559 .msg_controllen = sizeof(control),
560 };
371d72e0 561 struct ucred *ucred;
7079cfef 562 Manager *m = userdata;
7079cfef
LP
563 char *p, *e;
564 Transfer *t;
565 Iterator i;
566 ssize_t n;
567 int r;
568
3691bcf3
LP
569 n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
570 if (IN_SET(n, -EAGAIN, -EINTR))
571 return 0;
572 if (n < 0)
573 return (int) n;
7079cfef 574
1c8da044
LP
575 cmsg_close_all(&msghdr);
576
7079cfef
LP
577 if (msghdr.msg_flags & MSG_TRUNC) {
578 log_warning("Got overly long notification datagram, ignoring.");
579 return 0;
580 }
581
371d72e0 582 ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
7079cfef
LP
583 if (!ucred || ucred->pid <= 0) {
584 log_warning("Got notification datagram lacking credential information, ignoring.");
585 return 0;
586 }
587
588 HASHMAP_FOREACH(t, m->transfers, i)
589 if (ucred->pid == t->pid)
590 break;
591
592 if (!t) {
593 log_warning("Got notification datagram from unexpected peer, ignoring.");
594 return 0;
595 }
596
597 buf[n] = 0;
598
599 p = startswith(buf, "X_IMPORT_PROGRESS=");
600 if (!p) {
601 p = strstr(buf, "\nX_IMPORT_PROGRESS=");
602 if (!p)
603 return 0;
604
605 p += 19;
606 }
607
608 e = strchrnul(p, '\n');
609 *e = 0;
610
5a8582fb
LP
611 r = parse_percent(p);
612 if (r < 0) {
7079cfef
LP
613 log_warning("Got invalid percent value, ignoring.");
614 return 0;
615 }
616
5a8582fb 617 t->progress_percent = (unsigned) r;
7079cfef 618
5a8582fb 619 log_debug("Got percentage from client: %u%%", t->progress_percent);
7079cfef
LP
620 return 0;
621}
622
3d7415f4
LP
623static int manager_new(Manager **ret) {
624 _cleanup_(manager_unrefp) Manager *m = NULL;
7079cfef
LP
625 static const union sockaddr_union sa = {
626 .un.sun_family = AF_UNIX,
627 .un.sun_path = "/run/systemd/import/notify",
628 };
3d7415f4
LP
629 int r;
630
631 assert(ret);
632
633 m = new0(Manager, 1);
634 if (!m)
635 return -ENOMEM;
636
637 r = sd_event_default(&m->event);
638 if (r < 0)
639 return r;
640
641 sd_event_set_watchdog(m->event, true);
642
643 r = sd_bus_default_system(&m->bus);
644 if (r < 0)
645 return r;
646
7079cfef
LP
647 m->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
648 if (m->notify_fd < 0)
649 return -errno;
650
651 (void) mkdir_parents_label(sa.un.sun_path, 0755);
155b6876 652 (void) sockaddr_un_unlink(&sa.un);
7079cfef 653
fc2fffe7 654 if (bind(m->notify_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
7079cfef
LP
655 return -errno;
656
2ff48e98
LP
657 r = setsockopt_int(m->notify_fd, SOL_SOCKET, SO_PASSCRED, true);
658 if (r < 0)
659 return r;
7079cfef 660
ab09bf90
ZJS
661 r = sd_event_add_io(m->event, &m->notify_event_source,
662 m->notify_fd, EPOLLIN, manager_on_notify, m);
7079cfef
LP
663 if (r < 0)
664 return r;
665
1cc6c93a 666 *ret = TAKE_PTR(m);
3d7415f4
LP
667
668 return 0;
669}
670
b43d75c3 671static Transfer *manager_find(Manager *m, TransferType type, const char *remote) {
3d7415f4
LP
672 Transfer *t;
673 Iterator i;
674
675 assert(m);
676 assert(type >= 0);
677 assert(type < _TRANSFER_TYPE_MAX);
678
b0325c99
LP
679 HASHMAP_FOREACH(t, m->transfers, i)
680 if (t->type == type && streq_ptr(t->remote, remote))
3d7415f4 681 return t;
3d7415f4
LP
682
683 return NULL;
684}
685
19070062 686static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
b6e676ce
LP
687 _cleanup_(transfer_unrefp) Transfer *t = NULL;
688 int fd, force, read_only, r;
689 const char *local, *object;
690 Manager *m = userdata;
691 TransferType type;
1209ef94 692 struct stat st;
b6e676ce
LP
693 uint32_t id;
694
19070062
LP
695 assert(msg);
696 assert(m);
697
b6e676ce
LP
698 r = bus_verify_polkit_async(
699 msg,
700 CAP_SYS_ADMIN,
701 "org.freedesktop.import1.import",
403ed0e5 702 NULL,
b6e676ce
LP
703 false,
704 UID_INVALID,
705 &m->polkit_registry,
706 error);
707 if (r < 0)
708 return r;
709 if (r == 0)
710 return 1; /* Will call us back */
711
712 r = sd_bus_message_read(msg, "hsbb", &fd, &local, &force, &read_only);
713 if (r < 0)
714 return r;
715
1209ef94
AZ
716 if (fstat(fd, &st) < 0)
717 return -errno;
718
719 if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode))
720 return -EINVAL;
176a05c2 721
b6e676ce 722 if (!machine_name_is_valid(local))
ab09bf90
ZJS
723 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
724 "Local name %s is invalid", local);
b6e676ce 725
5f7ecd61 726 r = setup_machine_directory(error);
b6e676ce
LP
727 if (r < 0)
728 return r;
729
ab09bf90
ZJS
730 type = streq_ptr(sd_bus_message_get_member(msg), "ImportTar") ?
731 TRANSFER_IMPORT_TAR : TRANSFER_IMPORT_RAW;
b6e676ce
LP
732
733 r = transfer_new(m, &t);
734 if (r < 0)
735 return r;
736
737 t->type = type;
738 t->force_local = force;
739 t->read_only = read_only;
740
741 t->local = strdup(local);
742 if (!t->local)
743 return -ENOMEM;
744
745 t->stdin_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
746 if (t->stdin_fd < 0)
747 return -errno;
748
749 r = transfer_start(t);
750 if (r < 0)
751 return r;
752
753 object = t->object_path;
754 id = t->id;
755 t = NULL;
756
757 return sd_bus_reply_method_return(msg, "uo", id, object);
758}
759
1d7579c4
LP
760static int method_import_fs(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
761 _cleanup_(transfer_unrefp) Transfer *t = NULL;
762 int fd, force, read_only, r;
763 const char *local, *object;
764 Manager *m = userdata;
765 uint32_t id;
766
767 assert(msg);
768 assert(m);
769
770 r = bus_verify_polkit_async(
771 msg,
772 CAP_SYS_ADMIN,
773 "org.freedesktop.import1.import",
774 NULL,
775 false,
776 UID_INVALID,
777 &m->polkit_registry,
778 error);
779 if (r < 0)
780 return r;
781 if (r == 0)
782 return 1; /* Will call us back */
783
784 r = sd_bus_message_read(msg, "hsbb", &fd, &local, &force, &read_only);
785 if (r < 0)
786 return r;
787
176a05c2
LP
788 r = fd_verify_directory(fd);
789 if (r < 0)
790 return r;
791
1d7579c4 792 if (!machine_name_is_valid(local))
ab09bf90
ZJS
793 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
794 "Local name %s is invalid", local);
1d7579c4 795
5f7ecd61 796 r = setup_machine_directory(error);
1d7579c4
LP
797 if (r < 0)
798 return r;
799
800 r = transfer_new(m, &t);
801 if (r < 0)
802 return r;
803
804 t->type = TRANSFER_IMPORT_FS;
805 t->force_local = force;
806 t->read_only = read_only;
807
808 t->local = strdup(local);
809 if (!t->local)
810 return -ENOMEM;
811
812 t->stdin_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
813 if (t->stdin_fd < 0)
814 return -errno;
815
816 r = transfer_start(t);
817 if (r < 0)
818 return r;
819
820 object = t->object_path;
821 id = t->id;
822 t = NULL;
823
824 return sd_bus_reply_method_return(msg, "uo", id, object);
825}
826
19070062 827static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
587fec42
LP
828 _cleanup_(transfer_unrefp) Transfer *t = NULL;
829 int fd, r;
830 const char *local, *object, *format;
831 Manager *m = userdata;
832 TransferType type;
1209ef94 833 struct stat st;
587fec42
LP
834 uint32_t id;
835
19070062
LP
836 assert(msg);
837 assert(m);
838
587fec42
LP
839 r = bus_verify_polkit_async(
840 msg,
841 CAP_SYS_ADMIN,
842 "org.freedesktop.import1.export",
403ed0e5 843 NULL,
587fec42
LP
844 false,
845 UID_INVALID,
846 &m->polkit_registry,
847 error);
848 if (r < 0)
849 return r;
850 if (r == 0)
851 return 1; /* Will call us back */
852
853 r = sd_bus_message_read(msg, "shs", &local, &fd, &format);
854 if (r < 0)
855 return r;
856
857 if (!machine_name_is_valid(local))
ab09bf90
ZJS
858 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
859 "Local name %s is invalid", local);
587fec42 860
1209ef94
AZ
861 if (fstat(fd, &st) < 0)
862 return -errno;
863
864 if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode))
865 return -EINVAL;
176a05c2 866
ab09bf90
ZJS
867 type = streq_ptr(sd_bus_message_get_member(msg), "ExportTar") ?
868 TRANSFER_EXPORT_TAR : TRANSFER_EXPORT_RAW;
587fec42
LP
869
870 r = transfer_new(m, &t);
871 if (r < 0)
872 return r;
873
874 t->type = type;
875
876 if (!isempty(format)) {
877 t->format = strdup(format);
878 if (!t->format)
879 return -ENOMEM;
880 }
881
882 t->local = strdup(local);
883 if (!t->local)
884 return -ENOMEM;
885
886 t->stdout_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
887 if (t->stdout_fd < 0)
888 return -errno;
889
890 r = transfer_start(t);
891 if (r < 0)
892 return r;
893
894 object = t->object_path;
895 id = t->id;
896 t = NULL;
897
898 return sd_bus_reply_method_return(msg, "uo", id, object);
899}
900
19070062 901static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
3d7415f4
LP
902 _cleanup_(transfer_unrefp) Transfer *t = NULL;
903 const char *remote, *local, *verify, *object;
904 Manager *m = userdata;
905 ImportVerify v;
906 TransferType type;
907 int force, r;
908 uint32_t id;
909
3d7415f4
LP
910 assert(msg);
911 assert(m);
912
913 r = bus_verify_polkit_async(
914 msg,
915 CAP_SYS_ADMIN,
916 "org.freedesktop.import1.pull",
403ed0e5 917 NULL,
3d7415f4 918 false,
c529695e 919 UID_INVALID,
3d7415f4
LP
920 &m->polkit_registry,
921 error);
922 if (r < 0)
923 return r;
924 if (r == 0)
925 return 1; /* Will call us back */
926
927 r = sd_bus_message_read(msg, "sssb", &remote, &local, &verify, &force);
928 if (r < 0)
929 return r;
930
931 if (!http_url_is_valid(remote))
ab09bf90
ZJS
932 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
933 "URL %s is invalid", remote);
3d7415f4
LP
934
935 if (isempty(local))
936 local = NULL;
937 else if (!machine_name_is_valid(local))
ab09bf90
ZJS
938 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
939 "Local name %s is invalid", local);
3d7415f4
LP
940
941 if (isempty(verify))
942 v = IMPORT_VERIFY_SIGNATURE;
943 else
944 v = import_verify_from_string(verify);
945 if (v < 0)
ab09bf90
ZJS
946 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
947 "Unknown verification mode %s", verify);
3d7415f4 948
5f7ecd61 949 r = setup_machine_directory(error);
ce06fdfb
LP
950 if (r < 0)
951 return r;
952
ab09bf90
ZJS
953 type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ?
954 TRANSFER_PULL_TAR : TRANSFER_PULL_RAW;
3d7415f4 955
b43d75c3 956 if (manager_find(m, type, remote))
ab09bf90
ZJS
957 return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS,
958 "Transfer for %s already in progress.", remote);
3d7415f4
LP
959
960 r = transfer_new(m, &t);
961 if (r < 0)
962 return r;
963
964 t->type = type;
965 t->verify = v;
966 t->force_local = force;
967
968 t->remote = strdup(remote);
969 if (!t->remote)
970 return -ENOMEM;
971
b6e676ce
LP
972 if (local) {
973 t->local = strdup(local);
974 if (!t->local)
975 return -ENOMEM;
976 }
3d7415f4
LP
977
978 r = transfer_start(t);
979 if (r < 0)
980 return r;
981
982 object = t->object_path;
983 id = t->id;
984 t = NULL;
985
986 return sd_bus_reply_method_return(msg, "uo", id, object);
987}
988
19070062 989static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
4afd3348 990 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3d7415f4
LP
991 Manager *m = userdata;
992 Transfer *t;
993 Iterator i;
994 int r;
995
3d7415f4
LP
996 assert(msg);
997 assert(m);
998
999 r = sd_bus_message_new_method_return(msg, &reply);
1000 if (r < 0)
1001 return r;
1002
7079cfef 1003 r = sd_bus_message_open_container(reply, 'a', "(usssdo)");
3d7415f4
LP
1004 if (r < 0)
1005 return r;
1006
1007 HASHMAP_FOREACH(t, m->transfers, i) {
1008
1009 r = sd_bus_message_append(
1010 reply,
7079cfef 1011 "(usssdo)",
3d7415f4
LP
1012 t->id,
1013 transfer_type_to_string(t->type),
1014 t->remote,
1015 t->local,
1d7579c4 1016 transfer_percent_as_double(t),
3d7415f4
LP
1017 t->object_path);
1018 if (r < 0)
1019 return r;
1020 }
1021
1022 r = sd_bus_message_close_container(reply);
1023 if (r < 0)
1024 return r;
1025
9030ca46 1026 return sd_bus_send(NULL, reply, NULL);
3d7415f4
LP
1027}
1028
19070062 1029static int method_cancel(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
3d7415f4
LP
1030 Transfer *t = userdata;
1031 int r;
1032
3d7415f4
LP
1033 assert(msg);
1034 assert(t);
1035
1036 r = bus_verify_polkit_async(
1037 msg,
1038 CAP_SYS_ADMIN,
1039 "org.freedesktop.import1.pull",
403ed0e5 1040 NULL,
3d7415f4 1041 false,
c529695e 1042 UID_INVALID,
3d7415f4
LP
1043 &t->manager->polkit_registry,
1044 error);
1045 if (r < 0)
1046 return r;
1047 if (r == 0)
1048 return 1; /* Will call us back */
1049
1050 r = transfer_cancel(t);
1051 if (r < 0)
1052 return r;
1053
1054 return sd_bus_reply_method_return(msg, NULL);
1055}
1056
19070062 1057static int method_cancel_transfer(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
3d7415f4
LP
1058 Manager *m = userdata;
1059 Transfer *t;
1060 uint32_t id;
1061 int r;
1062
3d7415f4
LP
1063 assert(msg);
1064 assert(m);
1065
1066 r = bus_verify_polkit_async(
1067 msg,
1068 CAP_SYS_ADMIN,
1069 "org.freedesktop.import1.pull",
403ed0e5 1070 NULL,
3d7415f4 1071 false,
c529695e 1072 UID_INVALID,
3d7415f4
LP
1073 &m->polkit_registry,
1074 error);
1075 if (r < 0)
1076 return r;
1077 if (r == 0)
1078 return 1; /* Will call us back */
1079
1080 r = sd_bus_message_read(msg, "u", &id);
1081 if (r < 0)
1082 return r;
1083 if (id <= 0)
1084 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid transfer id");
1085
1086 t = hashmap_get(m->transfers, UINT32_TO_PTR(id));
1087 if (!t)
09d46cfd 1088 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_TRANSFER, "No transfer by id %" PRIu32, id);
3d7415f4
LP
1089
1090 r = transfer_cancel(t);
1091 if (r < 0)
1092 return r;
1093
1094 return sd_bus_reply_method_return(msg, NULL);
1095}
1096
7079cfef
LP
1097static int property_get_progress(
1098 sd_bus *bus,
1099 const char *path,
1100 const char *interface,
1101 const char *property,
1102 sd_bus_message *reply,
1103 void *userdata,
1104 sd_bus_error *error) {
1105
1106 Transfer *t = userdata;
1107
1108 assert(bus);
1109 assert(reply);
1110 assert(t);
1111
1d7579c4 1112 return sd_bus_message_append(reply, "d", transfer_percent_as_double(t));
7079cfef
LP
1113}
1114
3d7415f4
LP
1115static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, transfer_type, TransferType);
1116static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_verify, import_verify, ImportVerify);
1117
a3b7cf50
ZJS
1118static int transfer_object_find(
1119 sd_bus *bus,
1120 const char *path,
1121 const char *interface,
1122 void *userdata,
1123 void **found,
1124 sd_bus_error *error) {
1125
1126 Manager *m = userdata;
1127 Transfer *t;
1128 const char *p;
1129 uint32_t id;
1130 int r;
1131
1132 assert(bus);
1133 assert(path);
1134 assert(interface);
1135 assert(found);
1136 assert(m);
1137
1138 p = startswith(path, "/org/freedesktop/import1/transfer/_");
1139 if (!p)
1140 return 0;
1141
1142 r = safe_atou32(p, &id);
1143 if (r < 0 || id == 0)
1144 return 0;
1145
1146 t = hashmap_get(m->transfers, UINT32_TO_PTR(id));
1147 if (!t)
1148 return 0;
1149
1150 *found = t;
1151 return 1;
1152}
1153
1154static int transfer_node_enumerator(
1155 sd_bus *bus,
1156 const char *path,
1157 void *userdata,
1158 char ***nodes,
1159 sd_bus_error *error) {
1160
1161 _cleanup_strv_free_ char **l = NULL;
1162 Manager *m = userdata;
1163 Transfer *t;
1164 unsigned k = 0;
1165 Iterator i;
1166
1167 l = new0(char*, hashmap_size(m->transfers) + 1);
1168 if (!l)
1169 return -ENOMEM;
1170
1171 HASHMAP_FOREACH(t, m->transfers, i) {
1172
1173 l[k] = strdup(t->object_path);
1174 if (!l[k])
1175 return -ENOMEM;
1176
1177 k++;
1178 }
1179
1180 *nodes = TAKE_PTR(l);
1181
1182 return 1;
1183}
1184
3d7415f4
LP
1185static const sd_bus_vtable transfer_vtable[] = {
1186 SD_BUS_VTABLE_START(0),
956ecd3c 1187
3d7415f4
LP
1188 SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Transfer, id), SD_BUS_VTABLE_PROPERTY_CONST),
1189 SD_BUS_PROPERTY("Local", "s", NULL, offsetof(Transfer, local), SD_BUS_VTABLE_PROPERTY_CONST),
1190 SD_BUS_PROPERTY("Remote", "s", NULL, offsetof(Transfer, remote), SD_BUS_VTABLE_PROPERTY_CONST),
1191 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Transfer, type), SD_BUS_VTABLE_PROPERTY_CONST),
1192 SD_BUS_PROPERTY("Verify", "s", property_get_verify, offsetof(Transfer, verify), SD_BUS_VTABLE_PROPERTY_CONST),
7079cfef 1193 SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
956ecd3c 1194
3d7415f4 1195 SD_BUS_METHOD("Cancel", NULL, NULL, method_cancel, SD_BUS_VTABLE_UNPRIVILEGED),
956ecd3c
ZJS
1196
1197 SD_BUS_SIGNAL_WITH_NAMES("LogMessage",
1198 "us",
1199 SD_BUS_PARAM(priority)
1200 SD_BUS_PARAM(line),
1201 0),
1202
3d7415f4
LP
1203 SD_BUS_VTABLE_END,
1204};
1205
a3b7cf50
ZJS
1206static const BusObjectImplementation transfer_object = {
1207 "/org/freedesktop/import1/transfer",
1208 "org.freedesktop.import1.Transfer",
1209 .fallback_vtables = BUS_FALLBACK_VTABLES({transfer_vtable, transfer_object_find}),
1210 .node_enumerator = transfer_node_enumerator,
1211};
1212
3d7415f4
LP
1213static const sd_bus_vtable manager_vtable[] = {
1214 SD_BUS_VTABLE_START(0),
956ecd3c
ZJS
1215
1216 SD_BUS_METHOD_WITH_NAMES("ImportTar",
1217 "hsbb",
1218 SD_BUS_PARAM(fd)
1219 SD_BUS_PARAM(local_name)
1220 SD_BUS_PARAM(force)
1221 SD_BUS_PARAM(read_only),
1222 "uo",
1223 SD_BUS_PARAM(transfer_id)
1224 SD_BUS_PARAM(transfer_path),
1225 method_import_tar_or_raw,
1226 SD_BUS_VTABLE_UNPRIVILEGED),
1227 SD_BUS_METHOD_WITH_NAMES("ImportRaw",
1228 "hsbb",
1229 SD_BUS_PARAM(fd)
1230 SD_BUS_PARAM(local_name)
1231 SD_BUS_PARAM(force)
1232 SD_BUS_PARAM(read_only),
1233 "uo",
1234 SD_BUS_PARAM(transfer_id)
1235 SD_BUS_PARAM(transfer_path),
1236 method_import_tar_or_raw,
1237 SD_BUS_VTABLE_UNPRIVILEGED),
1238 SD_BUS_METHOD_WITH_NAMES("ImportFileSystem",
1239 "hsbb",
1240 SD_BUS_PARAM(fd)
1241 SD_BUS_PARAM(local_name)
1242 SD_BUS_PARAM(force)
1243 SD_BUS_PARAM(read_only),
1244 "uo",
1245 SD_BUS_PARAM(transfer_id)
1246 SD_BUS_PARAM(transfer_path),
1247 method_import_fs,
1248 SD_BUS_VTABLE_UNPRIVILEGED),
1249 SD_BUS_METHOD_WITH_NAMES("ExportTar",
1250 "shs",
1251 SD_BUS_PARAM(local_name)
1252 SD_BUS_PARAM(fd)
1253 SD_BUS_PARAM(format),
1254 "uo",
1255 SD_BUS_PARAM(transfer_id)
1256 SD_BUS_PARAM(transfer_path),
1257 method_export_tar_or_raw,
1258 SD_BUS_VTABLE_UNPRIVILEGED),
1259 SD_BUS_METHOD_WITH_NAMES("ExportRaw",
1260 "shs",
1261 SD_BUS_PARAM(local_name)
1262 SD_BUS_PARAM(fd)
1263 SD_BUS_PARAM(format),
1264 "uo",
1265 SD_BUS_PARAM(transfer_id)
1266 SD_BUS_PARAM(transfer_path),
1267 method_export_tar_or_raw,
1268 SD_BUS_VTABLE_UNPRIVILEGED),
1269 SD_BUS_METHOD_WITH_NAMES("PullTar",
1270 "sssb",
1271 SD_BUS_PARAM(url)
1272 SD_BUS_PARAM(local_name)
1273 SD_BUS_PARAM(verify_mode)
1274 SD_BUS_PARAM(force),
1275 "uo",
1276 SD_BUS_PARAM(transfer_id)
1277 SD_BUS_PARAM(transfer_path),
1278 method_pull_tar_or_raw,
1279 SD_BUS_VTABLE_UNPRIVILEGED),
1280 SD_BUS_METHOD_WITH_NAMES("PullRaw",
1281 "sssb",
1282 SD_BUS_PARAM(url)
1283 SD_BUS_PARAM(local_name)
1284 SD_BUS_PARAM(verify_mode)
1285 SD_BUS_PARAM(force),
1286 "uo",
1287 SD_BUS_PARAM(transfer_id)
1288 SD_BUS_PARAM(transfer_path),
1289 method_pull_tar_or_raw,
1290 SD_BUS_VTABLE_UNPRIVILEGED),
1291 SD_BUS_METHOD_WITH_NAMES("ListTransfers",
1292 NULL,,
1293 "a(usssdo)",
1294 SD_BUS_PARAM(transfers),
1295 method_list_transfers,
1296 SD_BUS_VTABLE_UNPRIVILEGED),
1297 SD_BUS_METHOD_WITH_NAMES("CancelTransfer",
1298 "u",
1299 SD_BUS_PARAM(transfer_id),
1300 NULL,,
1301 method_cancel_transfer,
1302 SD_BUS_VTABLE_UNPRIVILEGED),
1303
1304 SD_BUS_SIGNAL_WITH_NAMES("TransferNew",
1305 "uo",
1306 SD_BUS_PARAM(transfer_id)
1307 SD_BUS_PARAM(transfer_path),
1308 0),
1309 SD_BUS_SIGNAL_WITH_NAMES("TransferRemoved",
1310 "uos",
1311 SD_BUS_PARAM(transfer_id)
1312 SD_BUS_PARAM(transfer_path)
1313 SD_BUS_PARAM(result),
1314 0),
1315
3d7415f4
LP
1316 SD_BUS_VTABLE_END,
1317};
1318
a3b7cf50
ZJS
1319static const BusObjectImplementation manager_object = {
1320 "/org/freedesktop/import1",
1321 "org.freedesktop.import1.Manager",
1322 .vtables = BUS_VTABLES(manager_vtable),
1323 .children = BUS_IMPLEMENTATIONS(&transfer_object),
1324};
3d7415f4
LP
1325
1326static int manager_add_bus_objects(Manager *m) {
1327 int r;
1328
1329 assert(m);
1330
a3b7cf50 1331 r = bus_add_implementation(m->bus, &manager_object, m);
3d7415f4 1332 if (r < 0)
a3b7cf50 1333 return r;
3d7415f4 1334
ac9f55ed
LP
1335 r = bus_log_control_api_register(m->bus);
1336 if (r < 0)
1337 return r;
1338
0c0b9306 1339 r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.import1", 0, NULL, NULL);
3d7415f4 1340 if (r < 0)
0c0b9306 1341 return log_error_errno(r, "Failed to request name: %m");
3d7415f4
LP
1342
1343 r = sd_bus_attach_event(m->bus, m->event, 0);
1344 if (r < 0)
1345 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1346
1347 return 0;
1348}
1349
1350static bool manager_check_idle(void *userdata) {
1351 Manager *m = userdata;
1352
1353 return hashmap_isempty(m->transfers);
1354}
1355
1356static int manager_run(Manager *m) {
1357 assert(m);
1358
1359 return bus_event_loop_with_idle(
1360 m->event,
1361 m->bus,
1362 "org.freedesktop.import1",
1363 DEFAULT_EXIT_USEC,
1364 manager_check_idle,
1365 m);
1366}
1367
5272ae42 1368static int run(int argc, char *argv[]) {
3d7415f4
LP
1369 _cleanup_(manager_unrefp) Manager *m = NULL;
1370 int r;
1371
6bf3c61c 1372 log_setup_service();
3d7415f4 1373
fc021a5b
ZJS
1374 r = service_parse_argv("systemd-importd.service",
1375 "VM and container image import and export service.",
d4cc0edf
ZJS
1376 BUS_IMPLEMENTATIONS(&manager_object,
1377 &log_control_object),
fc021a5b
ZJS
1378 argc, argv);
1379 if (r <= 0)
1380 return r;
3d7415f4 1381
fc021a5b 1382 umask(0022);
3d7415f4 1383
72c0a2c2 1384 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
3d7415f4
LP
1385
1386 r = manager_new(&m);
5272ae42
ZJS
1387 if (r < 0)
1388 return log_error_errno(r, "Failed to allocate manager object: %m");
3d7415f4
LP
1389
1390 r = manager_add_bus_objects(m);
1391 if (r < 0)
5272ae42 1392 return r;
3d7415f4
LP
1393
1394 r = manager_run(m);
5272ae42
ZJS
1395 if (r < 0)
1396 return log_error_errno(r, "Failed to run event loop: %m");
3d7415f4 1397
5272ae42 1398 return 0;
3d7415f4 1399}
5272ae42
ZJS
1400
1401DEFINE_MAIN_FUNCTION(run);