File: | build-scan/../src/import/importd.c |
Warning: | line 206, column 16 Potential leak of memory pointed to by 'n' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include <sys/prctl.h> | |||
4 | #include <sys/wait.h> | |||
5 | ||||
6 | #include "sd-bus.h" | |||
7 | ||||
8 | #include "alloc-util.h" | |||
9 | #include "bus-common-errors.h" | |||
10 | #include "bus-util.h" | |||
11 | #include "def.h" | |||
12 | #include "fd-util.h" | |||
13 | #include "hostname-util.h" | |||
14 | #include "import-util.h" | |||
15 | #include "machine-pool.h" | |||
16 | #include "missing.h" | |||
17 | #include "mkdir.h" | |||
18 | #include "parse-util.h" | |||
19 | #include "path-util.h" | |||
20 | #include "process-util.h" | |||
21 | #include "signal-util.h" | |||
22 | #include "socket-util.h" | |||
23 | #include "string-table.h" | |||
24 | #include "strv.h" | |||
25 | #include "syslog-util.h" | |||
26 | #include "user-util.h" | |||
27 | #include "util.h" | |||
28 | #include "web-util.h" | |||
29 | ||||
30 | typedef struct Transfer Transfer; | |||
31 | typedef struct Manager Manager; | |||
32 | ||||
33 | typedef enum TransferType { | |||
34 | TRANSFER_IMPORT_TAR, | |||
35 | TRANSFER_IMPORT_RAW, | |||
36 | TRANSFER_EXPORT_TAR, | |||
37 | TRANSFER_EXPORT_RAW, | |||
38 | TRANSFER_PULL_TAR, | |||
39 | TRANSFER_PULL_RAW, | |||
40 | _TRANSFER_TYPE_MAX, | |||
41 | _TRANSFER_TYPE_INVALID = -1, | |||
42 | } TransferType; | |||
43 | ||||
44 | struct Transfer { | |||
45 | Manager *manager; | |||
46 | ||||
47 | uint32_t id; | |||
48 | char *object_path; | |||
49 | ||||
50 | TransferType type; | |||
51 | ImportVerify verify; | |||
52 | ||||
53 | char *remote; | |||
54 | char *local; | |||
55 | bool_Bool force_local; | |||
56 | bool_Bool read_only; | |||
57 | ||||
58 | char *format; | |||
59 | ||||
60 | pid_t pid; | |||
61 | ||||
62 | int log_fd; | |||
63 | ||||
64 | char log_message[LINE_MAX2048]; | |||
65 | size_t log_message_size; | |||
66 | ||||
67 | sd_event_source *pid_event_source; | |||
68 | sd_event_source *log_event_source; | |||
69 | ||||
70 | unsigned n_canceled; | |||
71 | unsigned progress_percent; | |||
72 | ||||
73 | int stdin_fd; | |||
74 | int stdout_fd; | |||
75 | }; | |||
76 | ||||
77 | struct Manager { | |||
78 | sd_event *event; | |||
79 | sd_bus *bus; | |||
80 | ||||
81 | uint32_t current_transfer_id; | |||
82 | Hashmap *transfers; | |||
83 | ||||
84 | Hashmap *polkit_registry; | |||
85 | ||||
86 | int notify_fd; | |||
87 | ||||
88 | sd_event_source *notify_event_source; | |||
89 | }; | |||
90 | ||||
91 | #define TRANSFERS_MAX64 64 | |||
92 | ||||
93 | static const char* const transfer_type_table[_TRANSFER_TYPE_MAX] = { | |||
94 | [TRANSFER_IMPORT_TAR] = "import-tar", | |||
95 | [TRANSFER_IMPORT_RAW] = "import-raw", | |||
96 | [TRANSFER_EXPORT_TAR] = "export-tar", | |||
97 | [TRANSFER_EXPORT_RAW] = "export-raw", | |||
98 | [TRANSFER_PULL_TAR] = "pull-tar", | |||
99 | [TRANSFER_PULL_RAW] = "pull-raw", | |||
100 | }; | |||
101 | ||||
102 | DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType)static const char *transfer_type_to_string(TransferType i) { if (i < 0 || i >= (TransferType) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(transfer_type_table), typeof (&*(transfer_type_table))), sizeof(transfer_type_table)/sizeof ((transfer_type_table)[0]), ((void)0)))) return ((void*)0); return transfer_type_table[i]; }; | |||
103 | ||||
104 | static Transfer *transfer_unref(Transfer *t) { | |||
105 | if (!t) | |||
106 | return NULL((void*)0); | |||
107 | ||||
108 | if (t->manager) | |||
109 | hashmap_remove(t->manager->transfers, UINT32_TO_PTR(t->id)((void *) ((uintptr_t) (t->id)))); | |||
110 | ||||
111 | sd_event_source_unref(t->pid_event_source); | |||
112 | sd_event_source_unref(t->log_event_source); | |||
113 | ||||
114 | free(t->remote); | |||
115 | free(t->local); | |||
116 | free(t->format); | |||
117 | free(t->object_path); | |||
118 | ||||
119 | if (t->pid > 0) { | |||
120 | (void) kill_and_sigcont(t->pid, SIGKILL9); | |||
121 | (void) wait_for_terminate(t->pid, NULL((void*)0)); | |||
122 | } | |||
123 | ||||
124 | safe_close(t->log_fd); | |||
125 | safe_close(t->stdin_fd); | |||
126 | safe_close(t->stdout_fd); | |||
127 | ||||
128 | return mfree(t); | |||
129 | } | |||
130 | ||||
131 | DEFINE_TRIVIAL_CLEANUP_FUNC(Transfer*, transfer_unref)static inline void transfer_unrefp(Transfer* *p) { if (*p) transfer_unref (*p); }; | |||
132 | ||||
133 | static int transfer_new(Manager *m, Transfer **ret) { | |||
134 | _cleanup_(transfer_unrefp)__attribute__((cleanup(transfer_unrefp))) Transfer *t = NULL((void*)0); | |||
135 | uint32_t id; | |||
136 | int r; | |||
137 | ||||
138 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/import/importd.c", 138, __PRETTY_FUNCTION__ ); } while (0); | |||
139 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/import/importd.c", 139, __PRETTY_FUNCTION__ ); } while (0); | |||
140 | ||||
141 | if (hashmap_size(m->transfers) >= TRANSFERS_MAX64) | |||
142 | return -E2BIG7; | |||
143 | ||||
144 | r = hashmap_ensure_allocated(&m->transfers, &trivial_hash_ops)internal_hashmap_ensure_allocated(&m->transfers, & trivial_hash_ops ); | |||
145 | if (r < 0) | |||
146 | return r; | |||
147 | ||||
148 | t = new0(Transfer, 1)((Transfer*) calloc((1), sizeof(Transfer))); | |||
149 | if (!t) | |||
150 | return -ENOMEM12; | |||
151 | ||||
152 | t->type = _TRANSFER_TYPE_INVALID; | |||
153 | t->log_fd = -1; | |||
154 | t->stdin_fd = -1; | |||
155 | t->stdout_fd = -1; | |||
156 | t->verify = _IMPORT_VERIFY_INVALID; | |||
157 | ||||
158 | id = m->current_transfer_id + 1; | |||
159 | ||||
160 | if (asprintf(&t->object_path, "/org/freedesktop/import1/transfer/_%" PRIu32"u", id) < 0) | |||
161 | return -ENOMEM12; | |||
162 | ||||
163 | r = hashmap_put(m->transfers, UINT32_TO_PTR(id)((void *) ((uintptr_t) (id))), t); | |||
164 | if (r < 0) | |||
165 | return r; | |||
166 | ||||
167 | m->current_transfer_id = id; | |||
168 | ||||
169 | t->manager = m; | |||
170 | t->id = id; | |||
171 | ||||
172 | *ret = TAKE_PTR(t)({ typeof(t) _ptr_ = (t); (t) = ((void*)0); _ptr_; }); | |||
173 | ||||
174 | return 0; | |||
175 | } | |||
176 | ||||
177 | static void transfer_send_log_line(Transfer *t, const char *line) { | |||
178 | int r, priority = LOG_INFO6; | |||
179 | ||||
180 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/import/importd.c", 180, __PRETTY_FUNCTION__ ); } while (0); | |||
181 | assert(line)do { if ((__builtin_expect(!!(!(line)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("line"), "../src/import/importd.c", 181, __PRETTY_FUNCTION__); } while (0); | |||
182 | ||||
183 | syslog_parse_priority(&line, &priority, true1); | |||
184 | ||||
185 | log_full(priority, "(transfer%" PRIu32 ") %s", t->id, line)({ int _level = (((priority))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/import/importd.c", 185, __func__, "(transfer%" "u" ") %s" , t->id, line) : -abs(_e); }); | |||
186 | ||||
187 | r = sd_bus_emit_signal( | |||
188 | t->manager->bus, | |||
189 | t->object_path, | |||
190 | "org.freedesktop.import1.Transfer", | |||
191 | "LogMessage", | |||
192 | "us", | |||
193 | priority, | |||
194 | line); | |||
195 | if (r < 0) | |||
196 | log_error_errno(r, "Cannot emit message: %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/import/importd.c", 196, __func__, "Cannot emit message: %m" ) : -abs(_e); }); | |||
197 | } | |||
198 | ||||
199 | static void transfer_send_logs(Transfer *t, bool_Bool flush) { | |||
200 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/import/importd.c", 200, __PRETTY_FUNCTION__ ); } while (0); | |||
201 | ||||
202 | /* Try to send out all log messages, if we can. But if we | |||
203 | * can't we remove the messages from the buffer, but don't | |||
204 | * fail */ | |||
205 | ||||
206 | while (t->log_message_size > 0) { | |||
| ||||
207 | _cleanup_free___attribute__((cleanup(freep))) char *n = NULL((void*)0); | |||
208 | char *e; | |||
209 | ||||
210 | if (t->log_message_size >= sizeof(t->log_message)) | |||
211 | e = t->log_message + sizeof(t->log_message); | |||
212 | else { | |||
213 | char *a, *b; | |||
214 | ||||
215 | a = memchr(t->log_message, 0, t->log_message_size); | |||
216 | b = memchr(t->log_message, '\n', t->log_message_size); | |||
217 | ||||
218 | if (a && b) | |||
219 | e = a < b ? a : b; | |||
220 | else if (a) | |||
221 | e = a; | |||
222 | else | |||
223 | e = b; | |||
224 | } | |||
225 | ||||
226 | if (!e
| |||
227 | if (!flush) | |||
228 | return; | |||
229 | ||||
230 | e = t->log_message + t->log_message_size; | |||
231 | } | |||
232 | ||||
233 | n = strndup(t->log_message, e - t->log_message); | |||
234 | ||||
235 | /* Skip over NUL and newlines */ | |||
236 | while (e < t->log_message + t->log_message_size && (*e == 0 || *e == '\n')) | |||
237 | e++; | |||
238 | ||||
239 | memmove(t->log_message, e, t->log_message + sizeof(t->log_message) - e); | |||
240 | t->log_message_size -= e - t->log_message; | |||
241 | ||||
242 | if (!n) { | |||
243 | log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/import/importd.c" , 243, __func__); | |||
244 | continue; | |||
245 | } | |||
246 | ||||
247 | if (isempty(n)) | |||
248 | continue; | |||
249 | ||||
250 | transfer_send_log_line(t, n); | |||
251 | } | |||
252 | } | |||
253 | ||||
254 | static int transfer_finalize(Transfer *t, bool_Bool success) { | |||
255 | int r; | |||
256 | ||||
257 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/import/importd.c", 257, __PRETTY_FUNCTION__ ); } while (0); | |||
258 | ||||
259 | transfer_send_logs(t, true1); | |||
260 | ||||
261 | r = sd_bus_emit_signal( | |||
262 | t->manager->bus, | |||
263 | "/org/freedesktop/import1", | |||
264 | "org.freedesktop.import1.Manager", | |||
265 | "TransferRemoved", | |||
266 | "uos", | |||
267 | t->id, | |||
268 | t->object_path, | |||
269 | success ? "done" : | |||
270 | t->n_canceled > 0 ? "canceled" : "failed"); | |||
271 | ||||
272 | if (r < 0) | |||
273 | log_error_errno(r, "Cannot emit message: %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/import/importd.c", 273, __func__, "Cannot emit message: %m" ) : -abs(_e); }); | |||
274 | ||||
275 | transfer_unref(t); | |||
276 | return 0; | |||
277 | } | |||
278 | ||||
279 | static int transfer_cancel(Transfer *t) { | |||
280 | int r; | |||
281 | ||||
282 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/import/importd.c", 282, __PRETTY_FUNCTION__ ); } while (0); | |||
283 | ||||
284 | r = kill_and_sigcont(t->pid, t->n_canceled < 3 ? SIGTERM15 : SIGKILL9); | |||
285 | if (r < 0) | |||
286 | return r; | |||
287 | ||||
288 | t->n_canceled++; | |||
289 | return 0; | |||
290 | } | |||
291 | ||||
292 | static int transfer_on_pid(sd_event_source *s, const siginfo_t *si, void *userdata) { | |||
293 | Transfer *t = userdata; | |||
294 | bool_Bool success = false0; | |||
295 | ||||
296 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/import/importd.c", 296, __PRETTY_FUNCTION__ ); } while (0); | |||
297 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/import/importd.c", 297, __PRETTY_FUNCTION__ ); } while (0); | |||
298 | ||||
299 | if (si->si_code == CLD_EXITEDCLD_EXITED) { | |||
300 | if (si->si_status_sifields._sigchld.si_status != 0) | |||
301 | log_error("Import process failed with exit code %i.", si->si_status)({ 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/import/importd.c", 301, __func__, "Import process failed with exit code %i." , si->_sifields._sigchld.si_status) : -abs(_e); }); | |||
302 | else { | |||
303 | log_debug("Import process succeeded.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/import/importd.c", 303, __func__, "Import process succeeded." ) : -abs(_e); }); | |||
304 | success = true1; | |||
305 | } | |||
306 | ||||
307 | } else if (IN_SET(si->si_code, CLD_KILLED, CLD_DUMPED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){CLD_KILLED, CLD_DUMPED})/sizeof(int)]; switch (si->si_code) { case CLD_KILLED: case CLD_DUMPED: _found = 1; break; default: break; } _found; })) | |||
308 | ||||
309 | log_error("Import process terminated by signal %s.", signal_to_string(si->si_status))({ 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/import/importd.c", 309, __func__, "Import process terminated by signal %s." , signal_to_string(si->_sifields._sigchld.si_status)) : -abs (_e); }); | |||
310 | else | |||
311 | log_error("Import process failed due to unknown reason.")({ 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/import/importd.c", 311, __func__, "Import process failed due to unknown reason." ) : -abs(_e); }); | |||
312 | ||||
313 | t->pid = 0; | |||
314 | ||||
315 | return transfer_finalize(t, success); | |||
316 | } | |||
317 | ||||
318 | static int transfer_on_log(sd_event_source *s, int fd, uint32_t revents, void *userdata) { | |||
319 | Transfer *t = userdata; | |||
320 | ssize_t l; | |||
321 | ||||
322 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/import/importd.c", 322, __PRETTY_FUNCTION__ ); } while (0); | |||
| ||||
323 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/import/importd.c", 323, __PRETTY_FUNCTION__ ); } while (0); | |||
324 | ||||
325 | l = read(fd, t->log_message + t->log_message_size, sizeof(t->log_message) - t->log_message_size); | |||
326 | if (l <= 0) { | |||
327 | /* EOF/read error. We just close the pipe here, and | |||
328 | * close the watch, waiting for the SIGCHLD to arrive, | |||
329 | * before we do anything else. */ | |||
330 | ||||
331 | if (l < 0) | |||
332 | log_error_errno(errno, "Failed to read log message: %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/import/importd.c", 332, __func__ , "Failed to read log message: %m") : -abs(_e); }); | |||
333 | ||||
334 | t->log_event_source = sd_event_source_unref(t->log_event_source); | |||
335 | return 0; | |||
336 | } | |||
337 | ||||
338 | t->log_message_size += l; | |||
339 | ||||
340 | transfer_send_logs(t, false0); | |||
341 | ||||
342 | return 0; | |||
343 | } | |||
344 | ||||
345 | static int transfer_start(Transfer *t) { | |||
346 | _cleanup_close_pair___attribute__((cleanup(close_pairp))) int pipefd[2] = { -1, -1 }; | |||
347 | int r; | |||
348 | ||||
349 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/import/importd.c", 349, __PRETTY_FUNCTION__ ); } while (0); | |||
350 | assert(t->pid <= 0)do { if ((__builtin_expect(!!(!(t->pid <= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t->pid <= 0"), "../src/import/importd.c" , 350, __PRETTY_FUNCTION__); } while (0); | |||
351 | ||||
352 | if (pipe2(pipefd, O_CLOEXEC02000000) < 0) | |||
353 | return -errno(*__errno_location ()); | |||
354 | ||||
355 | r = safe_fork("(sd-transfer)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &t->pid); | |||
356 | if (r < 0) | |||
357 | return r; | |||
358 | if (r == 0) { | |||
359 | const char *cmd[] = { | |||
360 | NULL((void*)0), /* systemd-import, systemd-export or systemd-pull */ | |||
361 | NULL((void*)0), /* tar, raw */ | |||
362 | NULL((void*)0), /* --verify= */ | |||
363 | NULL((void*)0), /* verify argument */ | |||
364 | NULL((void*)0), /* maybe --force */ | |||
365 | NULL((void*)0), /* maybe --read-only */ | |||
366 | NULL((void*)0), /* if so: the actual URL */ | |||
367 | NULL((void*)0), /* maybe --format= */ | |||
368 | NULL((void*)0), /* if so: the actual format */ | |||
369 | NULL((void*)0), /* remote */ | |||
370 | NULL((void*)0), /* local */ | |||
371 | NULL((void*)0) | |||
372 | }; | |||
373 | unsigned k = 0; | |||
374 | ||||
375 | /* Child */ | |||
376 | ||||
377 | pipefd[0] = safe_close(pipefd[0]); | |||
378 | ||||
379 | r = rearrange_stdio(t->stdin_fd, | |||
380 | t->stdout_fd < 0 ? pipefd[1] : t->stdout_fd, | |||
381 | pipefd[1]); | |||
382 | if (r < 0) { | |||
383 | log_error_errno(r, "Failed to set stdin/stdout/stderr: %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/import/importd.c", 383, __func__, "Failed to set stdin/stdout/stderr: %m" ) : -abs(_e); }); | |||
384 | _exit(EXIT_FAILURE1); | |||
385 | } | |||
386 | ||||
387 | if (setenv("SYSTEMD_LOG_TARGET", "console-prefixed", 1) < 0 || | |||
388 | setenv("NOTIFY_SOCKET", "/run/systemd/import/notify", 1) < 0) { | |||
389 | log_error_errno(errno, "setenv() failed: %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/import/importd.c", 389, __func__ , "setenv() failed: %m") : -abs(_e); }); | |||
390 | _exit(EXIT_FAILURE1); | |||
391 | } | |||
392 | ||||
393 | if (IN_SET(t->type, TRANSFER_IMPORT_TAR, TRANSFER_IMPORT_RAW)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){TRANSFER_IMPORT_TAR, TRANSFER_IMPORT_RAW })/sizeof(int)]; switch(t->type) { case TRANSFER_IMPORT_TAR : case TRANSFER_IMPORT_RAW: _found = 1; break; default: break ; } _found; })) | |||
394 | cmd[k++] = SYSTEMD_IMPORT_PATH"/usr/lib/systemd/systemd-import"; | |||
395 | else if (IN_SET(t->type, TRANSFER_EXPORT_TAR, TRANSFER_EXPORT_RAW)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){TRANSFER_EXPORT_TAR, TRANSFER_EXPORT_RAW })/sizeof(int)]; switch(t->type) { case TRANSFER_EXPORT_TAR : case TRANSFER_EXPORT_RAW: _found = 1; break; default: break ; } _found; })) | |||
396 | cmd[k++] = SYSTEMD_EXPORT_PATH"/usr/lib/systemd/systemd-export"; | |||
397 | else | |||
398 | cmd[k++] = SYSTEMD_PULL_PATH"/usr/lib/systemd/systemd-pull"; | |||
399 | ||||
400 | if (IN_SET(t->type, TRANSFER_IMPORT_TAR, TRANSFER_EXPORT_TAR, TRANSFER_PULL_TAR)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){TRANSFER_IMPORT_TAR, TRANSFER_EXPORT_TAR , TRANSFER_PULL_TAR})/sizeof(int)]; switch(t->type) { case TRANSFER_IMPORT_TAR: case TRANSFER_EXPORT_TAR: case TRANSFER_PULL_TAR : _found = 1; break; default: break; } _found; })) | |||
401 | cmd[k++] = "tar"; | |||
402 | else | |||
403 | cmd[k++] = "raw"; | |||
404 | ||||
405 | if (t->verify != _IMPORT_VERIFY_INVALID) { | |||
406 | cmd[k++] = "--verify"; | |||
407 | cmd[k++] = import_verify_to_string(t->verify); | |||
408 | } | |||
409 | ||||
410 | if (t->force_local) | |||
411 | cmd[k++] = "--force"; | |||
412 | if (t->read_only) | |||
413 | cmd[k++] = "--read-only"; | |||
414 | ||||
415 | if (t->format) { | |||
416 | cmd[k++] = "--format"; | |||
417 | cmd[k++] = t->format; | |||
418 | } | |||
419 | ||||
420 | if (!IN_SET(t->type, TRANSFER_EXPORT_TAR, TRANSFER_EXPORT_RAW)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){TRANSFER_EXPORT_TAR, TRANSFER_EXPORT_RAW })/sizeof(int)]; switch(t->type) { case TRANSFER_EXPORT_TAR : case TRANSFER_EXPORT_RAW: _found = 1; break; default: break ; } _found; })) { | |||
421 | if (t->remote) | |||
422 | cmd[k++] = t->remote; | |||
423 | else | |||
424 | cmd[k++] = "-"; | |||
425 | } | |||
426 | ||||
427 | if (t->local) | |||
428 | cmd[k++] = t->local; | |||
429 | cmd[k] = NULL((void*)0); | |||
430 | ||||
431 | execv(cmd[0], (char * const *) cmd); | |||
432 | log_error_errno(errno, "Failed to execute %s tool: %m", cmd[0])({ 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/import/importd.c", 432, __func__ , "Failed to execute %s tool: %m", cmd[0]) : -abs(_e); }); | |||
433 | _exit(EXIT_FAILURE1); | |||
434 | } | |||
435 | ||||
436 | pipefd[1] = safe_close(pipefd[1]); | |||
437 | t->log_fd = TAKE_FD(pipefd[0])({ int _fd_ = (pipefd[0]); (pipefd[0]) = -1; _fd_; }); | |||
438 | ||||
439 | t->stdin_fd = safe_close(t->stdin_fd); | |||
440 | ||||
441 | r = sd_event_add_child(t->manager->event, &t->pid_event_source, t->pid, WEXITED4, transfer_on_pid, t); | |||
442 | if (r < 0) | |||
443 | return r; | |||
444 | ||||
445 | r = sd_event_add_io(t->manager->event, &t->log_event_source, t->log_fd, EPOLLINEPOLLIN, transfer_on_log, t); | |||
446 | if (r < 0) | |||
447 | return r; | |||
448 | ||||
449 | /* Make sure always process logging before SIGCHLD */ | |||
450 | r = sd_event_source_set_priority(t->log_event_source, SD_EVENT_PRIORITY_NORMAL -5); | |||
451 | if (r < 0) | |||
452 | return r; | |||
453 | ||||
454 | r = sd_bus_emit_signal( | |||
455 | t->manager->bus, | |||
456 | "/org/freedesktop/import1", | |||
457 | "org.freedesktop.import1.Manager", | |||
458 | "TransferNew", | |||
459 | "uo", | |||
460 | t->id, | |||
461 | t->object_path); | |||
462 | if (r < 0) | |||
463 | return r; | |||
464 | ||||
465 | return 0; | |||
466 | } | |||
467 | ||||
468 | static Manager *manager_unref(Manager *m) { | |||
469 | Transfer *t; | |||
470 | ||||
471 | if (!m) | |||
472 | return NULL((void*)0); | |||
473 | ||||
474 | sd_event_source_unref(m->notify_event_source); | |||
475 | safe_close(m->notify_fd); | |||
476 | ||||
477 | while ((t = hashmap_first(m->transfers))) | |||
478 | transfer_unref(t); | |||
479 | ||||
480 | hashmap_free(m->transfers); | |||
481 | ||||
482 | bus_verify_polkit_async_registry_free(m->polkit_registry); | |||
483 | ||||
484 | m->bus = sd_bus_flush_close_unref(m->bus); | |||
485 | sd_event_unref(m->event); | |||
486 | ||||
487 | return mfree(m); | |||
488 | } | |||
489 | ||||
490 | DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref)static inline void manager_unrefp(Manager* *p) { if (*p) manager_unref (*p); }; | |||
491 | ||||
492 | static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void *userdata) { | |||
493 | ||||
494 | char buf[NOTIFY_BUFFER_MAX4096+1]; | |||
495 | struct iovec iovec = { | |||
496 | .iov_base = buf, | |||
497 | .iov_len = sizeof(buf)-1, | |||
498 | }; | |||
499 | union { | |||
500 | struct cmsghdr cmsghdr; | |||
501 | uint8_t buf[CMSG_SPACE(sizeof(struct ucred))((((sizeof(struct ucred)) + sizeof (size_t) - 1) & (size_t ) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1))) + | |||
502 | CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)((((sizeof(int) * 768) + sizeof (size_t) - 1) & (size_t) ~ (sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)))]; | |||
503 | } control = {}; | |||
504 | struct msghdr msghdr = { | |||
505 | .msg_iov = &iovec, | |||
506 | .msg_iovlen = 1, | |||
507 | .msg_control = &control, | |||
508 | .msg_controllen = sizeof(control), | |||
509 | }; | |||
510 | struct ucred *ucred = NULL((void*)0); | |||
511 | Manager *m = userdata; | |||
512 | struct cmsghdr *cmsg; | |||
513 | unsigned percent; | |||
514 | char *p, *e; | |||
515 | Transfer *t; | |||
516 | Iterator i; | |||
517 | ssize_t n; | |||
518 | int r; | |||
519 | ||||
520 | n = recvmsg(fd, &msghdr, MSG_DONTWAITMSG_DONTWAIT|MSG_CMSG_CLOEXECMSG_CMSG_CLOEXEC); | |||
521 | if (n < 0) { | |||
522 | if (IN_SET(errno, EAGAIN, EINTR)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){11, 4})/sizeof(int)]; switch((*__errno_location ())) { case 11: case 4: _found = 1; break; default: break; } _found; })) | |||
523 | return 0; | |||
524 | ||||
525 | return -errno(*__errno_location ()); | |||
526 | } | |||
527 | ||||
528 | cmsg_close_all(&msghdr); | |||
529 | ||||
530 | CMSG_FOREACH(cmsg, &msghdr)for ((cmsg) = ((size_t) (&msghdr)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msghdr)-> msg_control : (struct cmsghdr *) 0); (cmsg); (cmsg) = __cmsg_nxthdr ((&msghdr), (cmsg))) | |||
531 | if (cmsg->cmsg_level == SOL_SOCKET1 && | |||
532 | cmsg->cmsg_type == SCM_CREDENTIALSSCM_CREDENTIALS && | |||
533 | cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t ) ~(sizeof (size_t) - 1)) + (sizeof(struct ucred)))) | |||
534 | ucred = (struct ucred*) CMSG_DATA(cmsg)((cmsg)->__cmsg_data); | |||
535 | ||||
536 | if (msghdr.msg_flags & MSG_TRUNCMSG_TRUNC) { | |||
537 | log_warning("Got overly long notification datagram, 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/import/importd.c", 537, __func__, "Got overly long notification datagram, ignoring." ) : -abs(_e); }); | |||
538 | return 0; | |||
539 | } | |||
540 | ||||
541 | if (!ucred || ucred->pid <= 0) { | |||
542 | log_warning("Got notification datagram lacking credential information, 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/import/importd.c", 542, __func__, "Got notification datagram lacking credential information, ignoring." ) : -abs(_e); }); | |||
543 | return 0; | |||
544 | } | |||
545 | ||||
546 | HASHMAP_FOREACH(t, m->transfers, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); hashmap_iterate((m->transfers), & (i), (void**)&(t), ((void*)0)); ) | |||
547 | if (ucred->pid == t->pid) | |||
548 | break; | |||
549 | ||||
550 | if (!t) { | |||
551 | log_warning("Got notification datagram from unexpected peer, 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/import/importd.c", 551, __func__, "Got notification datagram from unexpected peer, ignoring." ) : -abs(_e); }); | |||
552 | return 0; | |||
553 | } | |||
554 | ||||
555 | buf[n] = 0; | |||
556 | ||||
557 | p = startswith(buf, "X_IMPORT_PROGRESS="); | |||
558 | if (!p) { | |||
559 | p = strstr(buf, "\nX_IMPORT_PROGRESS="); | |||
560 | if (!p) | |||
561 | return 0; | |||
562 | ||||
563 | p += 19; | |||
564 | } | |||
565 | ||||
566 | e = strchrnul(p, '\n'); | |||
567 | *e = 0; | |||
568 | ||||
569 | r = safe_atou(p, &percent); | |||
570 | if (r < 0 || percent > 100) { | |||
571 | log_warning("Got invalid percent value, 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/import/importd.c", 571, __func__, "Got invalid percent value, ignoring." ) : -abs(_e); }); | |||
572 | return 0; | |||
573 | } | |||
574 | ||||
575 | t->progress_percent = percent; | |||
576 | ||||
577 | log_debug("Got percentage from client: %u%%", percent)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/import/importd.c", 577, __func__, "Got percentage from client: %u%%" , percent) : -abs(_e); }); | |||
578 | return 0; | |||
579 | } | |||
580 | ||||
581 | static int manager_new(Manager **ret) { | |||
582 | _cleanup_(manager_unrefp)__attribute__((cleanup(manager_unrefp))) Manager *m = NULL((void*)0); | |||
583 | static const union sockaddr_union sa = { | |||
584 | .un.sun_family = AF_UNIX1, | |||
585 | .un.sun_path = "/run/systemd/import/notify", | |||
586 | }; | |||
587 | static const int one = 1; | |||
588 | int r; | |||
589 | ||||
590 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/import/importd.c", 590, __PRETTY_FUNCTION__ ); } while (0); | |||
591 | ||||
592 | m = new0(Manager, 1)((Manager*) calloc((1), sizeof(Manager))); | |||
593 | if (!m) | |||
594 | return -ENOMEM12; | |||
595 | ||||
596 | r = sd_event_default(&m->event); | |||
597 | if (r < 0) | |||
598 | return r; | |||
599 | ||||
600 | sd_event_set_watchdog(m->event, true1); | |||
601 | ||||
602 | r = sd_bus_default_system(&m->bus); | |||
603 | if (r < 0) | |||
604 | return r; | |||
605 | ||||
606 | m->notify_fd = socket(AF_UNIX1, SOCK_DGRAMSOCK_DGRAM|SOCK_CLOEXECSOCK_CLOEXEC|SOCK_NONBLOCKSOCK_NONBLOCK, 0); | |||
607 | if (m->notify_fd < 0) | |||
608 | return -errno(*__errno_location ()); | |||
609 | ||||
610 | (void) mkdir_parents_label(sa.un.sun_path, 0755); | |||
611 | (void) unlink(sa.un.sun_path); | |||
612 | ||||
613 | if (bind(m->notify_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)({ const struct sockaddr_un *_sa = &(sa.un); do { if ((__builtin_expect (!!(!(_sa->sun_family == 1)),0))) log_assert_failed_realm( LOG_REALM_SYSTEMD, ("_sa->sun_family == AF_UNIX"), "../src/import/importd.c" , 613, __PRETTY_FUNCTION__); } while (0); __builtin_offsetof( struct sockaddr_un, sun_path) + (_sa->sun_path[0] == 0 ? 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : strnlen (_sa->sun_path, sizeof(_sa->sun_path))); })) < 0) | |||
614 | return -errno(*__errno_location ()); | |||
615 | ||||
616 | if (setsockopt(m->notify_fd, SOL_SOCKET1, SO_PASSCRED16, &one, sizeof(one)) < 0) | |||
617 | return -errno(*__errno_location ()); | |||
618 | ||||
619 | r = sd_event_add_io(m->event, &m->notify_event_source, m->notify_fd, EPOLLINEPOLLIN, manager_on_notify, m); | |||
620 | if (r < 0) | |||
621 | return r; | |||
622 | ||||
623 | *ret = TAKE_PTR(m)({ typeof(m) _ptr_ = (m); (m) = ((void*)0); _ptr_; }); | |||
624 | ||||
625 | return 0; | |||
626 | } | |||
627 | ||||
628 | static Transfer *manager_find(Manager *m, TransferType type, const char *remote) { | |||
629 | Transfer *t; | |||
630 | Iterator i; | |||
631 | ||||
632 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/import/importd.c", 632, __PRETTY_FUNCTION__ ); } while (0); | |||
633 | assert(type >= 0)do { if ((__builtin_expect(!!(!(type >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("type >= 0"), "../src/import/importd.c" , 633, __PRETTY_FUNCTION__); } while (0); | |||
634 | assert(type < _TRANSFER_TYPE_MAX)do { if ((__builtin_expect(!!(!(type < _TRANSFER_TYPE_MAX) ),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("type < _TRANSFER_TYPE_MAX" ), "../src/import/importd.c", 634, __PRETTY_FUNCTION__); } while (0); | |||
635 | ||||
636 | HASHMAP_FOREACH(t, m->transfers, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); hashmap_iterate((m->transfers), & (i), (void**)&(t), ((void*)0)); ) { | |||
637 | ||||
638 | if (t->type == type && | |||
639 | streq_ptr(t->remote, remote)) | |||
640 | return t; | |||
641 | } | |||
642 | ||||
643 | return NULL((void*)0); | |||
644 | } | |||
645 | ||||
646 | static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) { | |||
647 | _cleanup_(transfer_unrefp)__attribute__((cleanup(transfer_unrefp))) Transfer *t = NULL((void*)0); | |||
648 | int fd, force, read_only, r; | |||
649 | const char *local, *object; | |||
650 | Manager *m = userdata; | |||
651 | TransferType type; | |||
652 | uint32_t id; | |||
653 | ||||
654 | assert(msg)do { if ((__builtin_expect(!!(!(msg)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("msg"), "../src/import/importd.c", 654, __PRETTY_FUNCTION__ ); } while (0); | |||
655 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/import/importd.c", 655, __PRETTY_FUNCTION__ ); } while (0); | |||
656 | ||||
657 | r = bus_verify_polkit_async( | |||
658 | msg, | |||
659 | CAP_SYS_ADMIN21, | |||
660 | "org.freedesktop.import1.import", | |||
661 | NULL((void*)0), | |||
662 | false0, | |||
663 | UID_INVALID((uid_t) -1), | |||
664 | &m->polkit_registry, | |||
665 | error); | |||
666 | if (r < 0) | |||
667 | return r; | |||
668 | if (r == 0) | |||
669 | return 1; /* Will call us back */ | |||
670 | ||||
671 | r = sd_bus_message_read(msg, "hsbb", &fd, &local, &force, &read_only); | |||
672 | if (r < 0) | |||
673 | return r; | |||
674 | ||||
675 | if (!machine_name_is_valid(local)hostname_is_valid(local, 0)) | |||
676 | return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Local name %s is invalid", local); | |||
677 | ||||
678 | r = setup_machine_directory((uint64_t) -1, error); | |||
679 | if (r < 0) | |||
680 | return r; | |||
681 | ||||
682 | type = streq_ptr(sd_bus_message_get_member(msg), "ImportTar") ? TRANSFER_IMPORT_TAR : TRANSFER_IMPORT_RAW; | |||
683 | ||||
684 | r = transfer_new(m, &t); | |||
685 | if (r < 0) | |||
686 | return r; | |||
687 | ||||
688 | t->type = type; | |||
689 | t->force_local = force; | |||
690 | t->read_only = read_only; | |||
691 | ||||
692 | t->local = strdup(local); | |||
693 | if (!t->local) | |||
694 | return -ENOMEM12; | |||
695 | ||||
696 | t->stdin_fd = fcntl(fd, F_DUPFD_CLOEXEC1030, 3); | |||
697 | if (t->stdin_fd < 0) | |||
698 | return -errno(*__errno_location ()); | |||
699 | ||||
700 | r = transfer_start(t); | |||
701 | if (r < 0) | |||
702 | return r; | |||
703 | ||||
704 | object = t->object_path; | |||
705 | id = t->id; | |||
706 | t = NULL((void*)0); | |||
707 | ||||
708 | return sd_bus_reply_method_return(msg, "uo", id, object); | |||
709 | } | |||
710 | ||||
711 | static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) { | |||
712 | _cleanup_(transfer_unrefp)__attribute__((cleanup(transfer_unrefp))) Transfer *t = NULL((void*)0); | |||
713 | int fd, r; | |||
714 | const char *local, *object, *format; | |||
715 | Manager *m = userdata; | |||
716 | TransferType type; | |||
717 | uint32_t id; | |||
718 | ||||
719 | assert(msg)do { if ((__builtin_expect(!!(!(msg)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("msg"), "../src/import/importd.c", 719, __PRETTY_FUNCTION__ ); } while (0); | |||
720 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/import/importd.c", 720, __PRETTY_FUNCTION__ ); } while (0); | |||
721 | ||||
722 | r = bus_verify_polkit_async( | |||
723 | msg, | |||
724 | CAP_SYS_ADMIN21, | |||
725 | "org.freedesktop.import1.export", | |||
726 | NULL((void*)0), | |||
727 | false0, | |||
728 | UID_INVALID((uid_t) -1), | |||
729 | &m->polkit_registry, | |||
730 | error); | |||
731 | if (r < 0) | |||
732 | return r; | |||
733 | if (r == 0) | |||
734 | return 1; /* Will call us back */ | |||
735 | ||||
736 | r = sd_bus_message_read(msg, "shs", &local, &fd, &format); | |||
737 | if (r < 0) | |||
738 | return r; | |||
739 | ||||
740 | if (!machine_name_is_valid(local)hostname_is_valid(local, 0)) | |||
741 | return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Local name %s is invalid", local); | |||
742 | ||||
743 | type = streq_ptr(sd_bus_message_get_member(msg), "ExportTar") ? TRANSFER_EXPORT_TAR : TRANSFER_EXPORT_RAW; | |||
744 | ||||
745 | r = transfer_new(m, &t); | |||
746 | if (r < 0) | |||
747 | return r; | |||
748 | ||||
749 | t->type = type; | |||
750 | ||||
751 | if (!isempty(format)) { | |||
752 | t->format = strdup(format); | |||
753 | if (!t->format) | |||
754 | return -ENOMEM12; | |||
755 | } | |||
756 | ||||
757 | t->local = strdup(local); | |||
758 | if (!t->local) | |||
759 | return -ENOMEM12; | |||
760 | ||||
761 | t->stdout_fd = fcntl(fd, F_DUPFD_CLOEXEC1030, 3); | |||
762 | if (t->stdout_fd < 0) | |||
763 | return -errno(*__errno_location ()); | |||
764 | ||||
765 | r = transfer_start(t); | |||
766 | if (r < 0) | |||
767 | return r; | |||
768 | ||||
769 | object = t->object_path; | |||
770 | id = t->id; | |||
771 | t = NULL((void*)0); | |||
772 | ||||
773 | return sd_bus_reply_method_return(msg, "uo", id, object); | |||
774 | } | |||
775 | ||||
776 | static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) { | |||
777 | _cleanup_(transfer_unrefp)__attribute__((cleanup(transfer_unrefp))) Transfer *t = NULL((void*)0); | |||
778 | const char *remote, *local, *verify, *object; | |||
779 | Manager *m = userdata; | |||
780 | ImportVerify v; | |||
781 | TransferType type; | |||
782 | int force, r; | |||
783 | uint32_t id; | |||
784 | ||||
785 | assert(msg)do { if ((__builtin_expect(!!(!(msg)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("msg"), "../src/import/importd.c", 785, __PRETTY_FUNCTION__ ); } while (0); | |||
786 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/import/importd.c", 786, __PRETTY_FUNCTION__ ); } while (0); | |||
787 | ||||
788 | r = bus_verify_polkit_async( | |||
789 | msg, | |||
790 | CAP_SYS_ADMIN21, | |||
791 | "org.freedesktop.import1.pull", | |||
792 | NULL((void*)0), | |||
793 | false0, | |||
794 | UID_INVALID((uid_t) -1), | |||
795 | &m->polkit_registry, | |||
796 | error); | |||
797 | if (r < 0) | |||
798 | return r; | |||
799 | if (r == 0) | |||
800 | return 1; /* Will call us back */ | |||
801 | ||||
802 | r = sd_bus_message_read(msg, "sssb", &remote, &local, &verify, &force); | |||
803 | if (r < 0) | |||
804 | return r; | |||
805 | ||||
806 | if (!http_url_is_valid(remote)) | |||
807 | return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "URL %s is invalid", remote); | |||
808 | ||||
809 | if (isempty(local)) | |||
810 | local = NULL((void*)0); | |||
811 | else if (!machine_name_is_valid(local)hostname_is_valid(local, 0)) | |||
812 | return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Local name %s is invalid", local); | |||
813 | ||||
814 | if (isempty(verify)) | |||
815 | v = IMPORT_VERIFY_SIGNATURE; | |||
816 | else | |||
817 | v = import_verify_from_string(verify); | |||
818 | if (v < 0) | |||
819 | return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Unknown verification mode %s", verify); | |||
820 | ||||
821 | r = setup_machine_directory((uint64_t) -1, error); | |||
822 | if (r < 0) | |||
823 | return r; | |||
824 | ||||
825 | type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ? TRANSFER_PULL_TAR : TRANSFER_PULL_RAW; | |||
826 | ||||
827 | if (manager_find(m, type, remote)) | |||
828 | return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS"org.freedesktop.import1.TransferInProgress", "Transfer for %s already in progress.", remote); | |||
829 | ||||
830 | r = transfer_new(m, &t); | |||
831 | if (r < 0) | |||
832 | return r; | |||
833 | ||||
834 | t->type = type; | |||
835 | t->verify = v; | |||
836 | t->force_local = force; | |||
837 | ||||
838 | t->remote = strdup(remote); | |||
839 | if (!t->remote) | |||
840 | return -ENOMEM12; | |||
841 | ||||
842 | if (local) { | |||
843 | t->local = strdup(local); | |||
844 | if (!t->local) | |||
845 | return -ENOMEM12; | |||
846 | } | |||
847 | ||||
848 | r = transfer_start(t); | |||
849 | if (r < 0) | |||
850 | return r; | |||
851 | ||||
852 | object = t->object_path; | |||
853 | id = t->id; | |||
854 | t = NULL((void*)0); | |||
855 | ||||
856 | return sd_bus_reply_method_return(msg, "uo", id, object); | |||
857 | } | |||
858 | ||||
859 | static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_error *error) { | |||
860 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *reply = NULL((void*)0); | |||
861 | Manager *m = userdata; | |||
862 | Transfer *t; | |||
863 | Iterator i; | |||
864 | int r; | |||
865 | ||||
866 | assert(msg)do { if ((__builtin_expect(!!(!(msg)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("msg"), "../src/import/importd.c", 866, __PRETTY_FUNCTION__ ); } while (0); | |||
867 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/import/importd.c", 867, __PRETTY_FUNCTION__ ); } while (0); | |||
868 | ||||
869 | r = sd_bus_message_new_method_return(msg, &reply); | |||
870 | if (r < 0) | |||
871 | return r; | |||
872 | ||||
873 | r = sd_bus_message_open_container(reply, 'a', "(usssdo)"); | |||
874 | if (r < 0) | |||
875 | return r; | |||
876 | ||||
877 | HASHMAP_FOREACH(t, m->transfers, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); hashmap_iterate((m->transfers), & (i), (void**)&(t), ((void*)0)); ) { | |||
878 | ||||
879 | r = sd_bus_message_append( | |||
880 | reply, | |||
881 | "(usssdo)", | |||
882 | t->id, | |||
883 | transfer_type_to_string(t->type), | |||
884 | t->remote, | |||
885 | t->local, | |||
886 | (double) t->progress_percent / 100.0, | |||
887 | t->object_path); | |||
888 | if (r < 0) | |||
889 | return r; | |||
890 | } | |||
891 | ||||
892 | r = sd_bus_message_close_container(reply); | |||
893 | if (r < 0) | |||
894 | return r; | |||
895 | ||||
896 | return sd_bus_send(NULL((void*)0), reply, NULL((void*)0)); | |||
897 | } | |||
898 | ||||
899 | static int method_cancel(sd_bus_message *msg, void *userdata, sd_bus_error *error) { | |||
900 | Transfer *t = userdata; | |||
901 | int r; | |||
902 | ||||
903 | assert(msg)do { if ((__builtin_expect(!!(!(msg)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("msg"), "../src/import/importd.c", 903, __PRETTY_FUNCTION__ ); } while (0); | |||
904 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/import/importd.c", 904, __PRETTY_FUNCTION__ ); } while (0); | |||
905 | ||||
906 | r = bus_verify_polkit_async( | |||
907 | msg, | |||
908 | CAP_SYS_ADMIN21, | |||
909 | "org.freedesktop.import1.pull", | |||
910 | NULL((void*)0), | |||
911 | false0, | |||
912 | UID_INVALID((uid_t) -1), | |||
913 | &t->manager->polkit_registry, | |||
914 | error); | |||
915 | if (r < 0) | |||
916 | return r; | |||
917 | if (r == 0) | |||
918 | return 1; /* Will call us back */ | |||
919 | ||||
920 | r = transfer_cancel(t); | |||
921 | if (r < 0) | |||
922 | return r; | |||
923 | ||||
924 | return sd_bus_reply_method_return(msg, NULL((void*)0)); | |||
925 | } | |||
926 | ||||
927 | static int method_cancel_transfer(sd_bus_message *msg, void *userdata, sd_bus_error *error) { | |||
928 | Manager *m = userdata; | |||
929 | Transfer *t; | |||
930 | uint32_t id; | |||
931 | int r; | |||
932 | ||||
933 | assert(msg)do { if ((__builtin_expect(!!(!(msg)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("msg"), "../src/import/importd.c", 933, __PRETTY_FUNCTION__ ); } while (0); | |||
934 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/import/importd.c", 934, __PRETTY_FUNCTION__ ); } while (0); | |||
935 | ||||
936 | r = bus_verify_polkit_async( | |||
937 | msg, | |||
938 | CAP_SYS_ADMIN21, | |||
939 | "org.freedesktop.import1.pull", | |||
940 | NULL((void*)0), | |||
941 | false0, | |||
942 | UID_INVALID((uid_t) -1), | |||
943 | &m->polkit_registry, | |||
944 | error); | |||
945 | if (r < 0) | |||
946 | return r; | |||
947 | if (r == 0) | |||
948 | return 1; /* Will call us back */ | |||
949 | ||||
950 | r = sd_bus_message_read(msg, "u", &id); | |||
951 | if (r < 0) | |||
952 | return r; | |||
953 | if (id <= 0) | |||
954 | return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Invalid transfer id"); | |||
955 | ||||
956 | t = hashmap_get(m->transfers, UINT32_TO_PTR(id)((void *) ((uintptr_t) (id)))); | |||
957 | if (!t) | |||
958 | return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_TRANSFER"org.freedesktop.import1.NoSuchTransfer", "No transfer by id %" PRIu32"u", id); | |||
959 | ||||
960 | r = transfer_cancel(t); | |||
961 | if (r < 0) | |||
962 | return r; | |||
963 | ||||
964 | return sd_bus_reply_method_return(msg, NULL((void*)0)); | |||
965 | } | |||
966 | ||||
967 | static int property_get_progress( | |||
968 | sd_bus *bus, | |||
969 | const char *path, | |||
970 | const char *interface, | |||
971 | const char *property, | |||
972 | sd_bus_message *reply, | |||
973 | void *userdata, | |||
974 | sd_bus_error *error) { | |||
975 | ||||
976 | Transfer *t = userdata; | |||
977 | ||||
978 | assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("bus"), "../src/import/importd.c", 978, __PRETTY_FUNCTION__ ); } while (0); | |||
979 | assert(reply)do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("reply"), "../src/import/importd.c", 979 , __PRETTY_FUNCTION__); } while (0); | |||
980 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/import/importd.c", 980, __PRETTY_FUNCTION__ ); } while (0); | |||
981 | ||||
982 | return sd_bus_message_append(reply, "d", (double) t->progress_percent / 100.0); | |||
983 | } | |||
984 | ||||
985 | static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, transfer_type, TransferType)int property_get_type(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { TransferType *data = userdata ; do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("bus"), "../src/import/importd.c", 985, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("reply"), "../src/import/importd.c", 985 , __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(data)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "data"), "../src/import/importd.c", 985, __PRETTY_FUNCTION__) ; } while (0); return sd_bus_message_append(reply, "s", transfer_type_to_string ((*(data)))); }; | |||
986 | static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_verify, import_verify, ImportVerify)int property_get_verify(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ImportVerify *data = userdata ; do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("bus"), "../src/import/importd.c", 986, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("reply"), "../src/import/importd.c", 986 , __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(data)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "data"), "../src/import/importd.c", 986, __PRETTY_FUNCTION__) ; } while (0); return sd_bus_message_append(reply, "s", import_verify_to_string ((*(data)))); }; | |||
987 | ||||
988 | static const sd_bus_vtable transfer_vtable[] = { | |||
989 | SD_BUS_VTABLE_START(0){ .type = _SD_BUS_VTABLE_START, .flags = 0, .x = { .start = { .element_size = sizeof(sd_bus_vtable) }, }, }, | |||
990 | SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Transfer, id), SD_BUS_VTABLE_PROPERTY_CONST){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = SD_BUS_VTABLE_PROPERTY_CONST , .x = { .property = { .member = "Id", .signature = "u", .get = ((void*)0), .set = ((void*)0), .offset = __builtin_offsetof (Transfer, id), }, }, }, | |||
991 | SD_BUS_PROPERTY("Local", "s", NULL, offsetof(Transfer, local), SD_BUS_VTABLE_PROPERTY_CONST){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = SD_BUS_VTABLE_PROPERTY_CONST , .x = { .property = { .member = "Local", .signature = "s", . get = ((void*)0), .set = ((void*)0), .offset = __builtin_offsetof (Transfer, local), }, }, }, | |||
992 | SD_BUS_PROPERTY("Remote", "s", NULL, offsetof(Transfer, remote), SD_BUS_VTABLE_PROPERTY_CONST){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = SD_BUS_VTABLE_PROPERTY_CONST , .x = { .property = { .member = "Remote", .signature = "s", . get = ((void*)0), .set = ((void*)0), .offset = __builtin_offsetof (Transfer, remote), }, }, }, | |||
993 | SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Transfer, type), SD_BUS_VTABLE_PROPERTY_CONST){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = SD_BUS_VTABLE_PROPERTY_CONST , .x = { .property = { .member = "Type", .signature = "s", .get = property_get_type, .set = ((void*)0), .offset = __builtin_offsetof (Transfer, type), }, }, }, | |||
994 | SD_BUS_PROPERTY("Verify", "s", property_get_verify, offsetof(Transfer, verify), SD_BUS_VTABLE_PROPERTY_CONST){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = SD_BUS_VTABLE_PROPERTY_CONST , .x = { .property = { .member = "Verify", .signature = "s", . get = property_get_verify, .set = ((void*)0), .offset = __builtin_offsetof (Transfer, verify), }, }, }, | |||
995 | SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = 0, .x = { .property = { .member = "Progress", .signature = "d", .get = property_get_progress , .set = ((void*)0), .offset = 0, }, }, }, | |||
996 | SD_BUS_METHOD("Cancel", NULL, NULL, method_cancel, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED , .x = { .method = { .member = "Cancel", .signature = ((void* )0), .result = ((void*)0), .handler = method_cancel, .offset = 0, }, }, }, | |||
997 | SD_BUS_SIGNAL("LogMessage", "us", 0){ .type = _SD_BUS_VTABLE_SIGNAL, .flags = 0, .x = { .signal = { .member = "LogMessage", .signature = "us", }, }, }, | |||
998 | SD_BUS_VTABLE_END{ .type = _SD_BUS_VTABLE_END, .flags = 0, .x = { { 0 } }, }, | |||
999 | }; | |||
1000 | ||||
1001 | static const sd_bus_vtable manager_vtable[] = { | |||
1002 | SD_BUS_VTABLE_START(0){ .type = _SD_BUS_VTABLE_START, .flags = 0, .x = { .start = { .element_size = sizeof(sd_bus_vtable) }, }, }, | |||
1003 | SD_BUS_METHOD("ImportTar", "hsbb", "uo", method_import_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED , .x = { .method = { .member = "ImportTar", .signature = "hsbb" , .result = "uo", .handler = method_import_tar_or_raw, .offset = 0, }, }, }, | |||
1004 | SD_BUS_METHOD("ImportRaw", "hsbb", "uo", method_import_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED , .x = { .method = { .member = "ImportRaw", .signature = "hsbb" , .result = "uo", .handler = method_import_tar_or_raw, .offset = 0, }, }, }, | |||
1005 | SD_BUS_METHOD("ExportTar", "shs", "uo", method_export_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED , .x = { .method = { .member = "ExportTar", .signature = "shs" , .result = "uo", .handler = method_export_tar_or_raw, .offset = 0, }, }, }, | |||
1006 | SD_BUS_METHOD("ExportRaw", "shs", "uo", method_export_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED , .x = { .method = { .member = "ExportRaw", .signature = "shs" , .result = "uo", .handler = method_export_tar_or_raw, .offset = 0, }, }, }, | |||
1007 | SD_BUS_METHOD("PullTar", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED , .x = { .method = { .member = "PullTar", .signature = "sssb" , .result = "uo", .handler = method_pull_tar_or_raw, .offset = 0, }, }, }, | |||
1008 | SD_BUS_METHOD("PullRaw", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED , .x = { .method = { .member = "PullRaw", .signature = "sssb" , .result = "uo", .handler = method_pull_tar_or_raw, .offset = 0, }, }, }, | |||
1009 | SD_BUS_METHOD("ListTransfers", NULL, "a(usssdo)", method_list_transfers, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED , .x = { .method = { .member = "ListTransfers", .signature = ( (void*)0), .result = "a(usssdo)", .handler = method_list_transfers , .offset = 0, }, }, }, | |||
1010 | SD_BUS_METHOD("CancelTransfer", "u", NULL, method_cancel_transfer, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED , .x = { .method = { .member = "CancelTransfer", .signature = "u", .result = ((void*)0), .handler = method_cancel_transfer , .offset = 0, }, }, }, | |||
1011 | SD_BUS_SIGNAL("TransferNew", "uo", 0){ .type = _SD_BUS_VTABLE_SIGNAL, .flags = 0, .x = { .signal = { .member = "TransferNew", .signature = "uo", }, }, }, | |||
1012 | SD_BUS_SIGNAL("TransferRemoved", "uos", 0){ .type = _SD_BUS_VTABLE_SIGNAL, .flags = 0, .x = { .signal = { .member = "TransferRemoved", .signature = "uos", }, }, }, | |||
1013 | SD_BUS_VTABLE_END{ .type = _SD_BUS_VTABLE_END, .flags = 0, .x = { { 0 } }, }, | |||
1014 | }; | |||
1015 | ||||
1016 | static int transfer_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { | |||
1017 | Manager *m = userdata; | |||
1018 | Transfer *t; | |||
1019 | const char *p; | |||
1020 | uint32_t id; | |||
1021 | int r; | |||
1022 | ||||
1023 | assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("bus"), "../src/import/importd.c", 1023, __PRETTY_FUNCTION__); } while (0); | |||
1024 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/import/importd.c", 1024 , __PRETTY_FUNCTION__); } while (0); | |||
1025 | assert(interface)do { if ((__builtin_expect(!!(!(interface)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("interface"), "../src/import/importd.c", 1025, __PRETTY_FUNCTION__); } while (0); | |||
1026 | assert(found)do { if ((__builtin_expect(!!(!(found)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("found"), "../src/import/importd.c", 1026 , __PRETTY_FUNCTION__); } while (0); | |||
1027 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/import/importd.c", 1027, __PRETTY_FUNCTION__ ); } while (0); | |||
1028 | ||||
1029 | p = startswith(path, "/org/freedesktop/import1/transfer/_"); | |||
1030 | if (!p) | |||
1031 | return 0; | |||
1032 | ||||
1033 | r = safe_atou32(p, &id); | |||
1034 | if (r < 0 || id == 0) | |||
1035 | return 0; | |||
1036 | ||||
1037 | t = hashmap_get(m->transfers, UINT32_TO_PTR(id)((void *) ((uintptr_t) (id)))); | |||
1038 | if (!t) | |||
1039 | return 0; | |||
1040 | ||||
1041 | *found = t; | |||
1042 | return 1; | |||
1043 | } | |||
1044 | ||||
1045 | static int transfer_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { | |||
1046 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **l = NULL((void*)0); | |||
1047 | Manager *m = userdata; | |||
1048 | Transfer *t; | |||
1049 | unsigned k = 0; | |||
1050 | Iterator i; | |||
1051 | ||||
1052 | l = new0(char*, hashmap_size(m->transfers) + 1)((char**) calloc((hashmap_size(m->transfers) + 1), sizeof( char*))); | |||
1053 | if (!l) | |||
1054 | return -ENOMEM12; | |||
1055 | ||||
1056 | HASHMAP_FOREACH(t, m->transfers, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); hashmap_iterate((m->transfers), & (i), (void**)&(t), ((void*)0)); ) { | |||
1057 | ||||
1058 | l[k] = strdup(t->object_path); | |||
1059 | if (!l[k]) | |||
1060 | return -ENOMEM12; | |||
1061 | ||||
1062 | k++; | |||
1063 | } | |||
1064 | ||||
1065 | *nodes = TAKE_PTR(l)({ typeof(l) _ptr_ = (l); (l) = ((void*)0); _ptr_; }); | |||
1066 | ||||
1067 | return 1; | |||
1068 | } | |||
1069 | ||||
1070 | static int manager_add_bus_objects(Manager *m) { | |||
1071 | int r; | |||
1072 | ||||
1073 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/import/importd.c", 1073, __PRETTY_FUNCTION__ ); } while (0); | |||
1074 | ||||
1075 | r = sd_bus_add_object_vtable(m->bus, NULL((void*)0), "/org/freedesktop/import1", "org.freedesktop.import1.Manager", manager_vtable, m); | |||
1076 | if (r < 0) | |||
1077 | return log_error_errno(r, "Failed to register object: %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/import/importd.c", 1077, __func__, "Failed to register object: %m" ) : -abs(_e); }); | |||
1078 | ||||
1079 | r = sd_bus_add_fallback_vtable(m->bus, NULL((void*)0), "/org/freedesktop/import1/transfer", "org.freedesktop.import1.Transfer", transfer_vtable, transfer_object_find, m); | |||
1080 | if (r < 0) | |||
1081 | return log_error_errno(r, "Failed to register object: %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/import/importd.c", 1081, __func__, "Failed to register object: %m" ) : -abs(_e); }); | |||
1082 | ||||
1083 | r = sd_bus_add_node_enumerator(m->bus, NULL((void*)0), "/org/freedesktop/import1/transfer", transfer_node_enumerator, m); | |||
1084 | if (r < 0) | |||
1085 | return log_error_errno(r, "Failed to add transfer enumerator: %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/import/importd.c", 1085, __func__, "Failed to add transfer enumerator: %m" ) : -abs(_e); }); | |||
1086 | ||||
1087 | r = sd_bus_request_name_async(m->bus, NULL((void*)0), "org.freedesktop.import1", 0, NULL((void*)0), NULL((void*)0)); | |||
1088 | if (r < 0) | |||
1089 | return log_error_errno(r, "Failed to request name: %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/import/importd.c", 1089, __func__, "Failed to request name: %m" ) : -abs(_e); }); | |||
1090 | ||||
1091 | r = sd_bus_attach_event(m->bus, m->event, 0); | |||
1092 | if (r < 0) | |||
1093 | return log_error_errno(r, "Failed to attach bus to event loop: %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/import/importd.c", 1093, __func__, "Failed to attach bus to event loop: %m" ) : -abs(_e); }); | |||
1094 | ||||
1095 | return 0; | |||
1096 | } | |||
1097 | ||||
1098 | static bool_Bool manager_check_idle(void *userdata) { | |||
1099 | Manager *m = userdata; | |||
1100 | ||||
1101 | return hashmap_isempty(m->transfers); | |||
1102 | } | |||
1103 | ||||
1104 | static int manager_run(Manager *m) { | |||
1105 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/import/importd.c", 1105, __PRETTY_FUNCTION__ ); } while (0); | |||
1106 | ||||
1107 | return bus_event_loop_with_idle( | |||
1108 | m->event, | |||
1109 | m->bus, | |||
1110 | "org.freedesktop.import1", | |||
1111 | DEFAULT_EXIT_USEC(30*((usec_t) 1000000ULL)), | |||
1112 | manager_check_idle, | |||
1113 | m); | |||
1114 | } | |||
1115 | ||||
1116 | int main(int argc, char *argv[]) { | |||
1117 | _cleanup_(manager_unrefp)__attribute__((cleanup(manager_unrefp))) Manager *m = NULL((void*)0); | |||
1118 | int r; | |||
1119 | ||||
1120 | log_set_target(LOG_TARGET_AUTO); | |||
1121 | log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD); | |||
1122 | log_open(); | |||
1123 | ||||
1124 | umask(0022); | |||
1125 | ||||
1126 | if (argc != 1) { | |||
1127 | log_error("This program takes no arguments.")({ 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/import/importd.c", 1127, __func__, "This program takes no arguments." ) : -abs(_e); }); | |||
1128 | r = -EINVAL22; | |||
1129 | goto finish; | |||
1130 | } | |||
1131 | ||||
1132 | assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0)do { if ((__builtin_expect(!!(!(sigprocmask_many(0, ((void*)0 ), 17, -1) >= 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0"), "../src/import/importd.c", 1132, __PRETTY_FUNCTION__); } while (0); | |||
1133 | ||||
1134 | r = manager_new(&m); | |||
1135 | if (r < 0) { | |||
1136 | log_error_errno(r, "Failed to allocate manager object: %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/import/importd.c", 1136, __func__, "Failed to allocate manager object: %m" ) : -abs(_e); }); | |||
1137 | goto finish; | |||
1138 | } | |||
1139 | ||||
1140 | r = manager_add_bus_objects(m); | |||
1141 | if (r < 0) | |||
1142 | goto finish; | |||
1143 | ||||
1144 | r = manager_run(m); | |||
1145 | if (r < 0) { | |||
1146 | log_error_errno(r, "Failed to run event loop: %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/import/importd.c", 1146, __func__, "Failed to run event loop: %m" ) : -abs(_e); }); | |||
1147 | goto finish; | |||
1148 | } | |||
1149 | ||||
1150 | finish: | |||
1151 | return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0; | |||
1152 | } |