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