]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/import/pull-tar.c
Merge pull request #20303 from andir/sysconfig-example
[thirdparty/systemd.git] / src / import / pull-tar.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
56ebfaf1 2
56ebfaf1 3#include <curl/curl.h>
cf0fbc49 4#include <sys/prctl.h>
56ebfaf1 5
7079cfef 6#include "sd-daemon.h"
07630cea 7
b5efdb8a 8#include "alloc-util.h"
56ebfaf1 9#include "btrfs-util.h"
07630cea
LP
10#include "copy.h"
11#include "curl-util.h"
3ffd4af2 12#include "fd-util.h"
f4f15635 13#include "fs-util.h"
07630cea
LP
14#include "hostname-util.h"
15#include "import-common.h"
16#include "import-util.h"
c40d82ab 17#include "install-file.h"
56ebfaf1
LP
18#include "macro.h"
19#include "mkdir.h"
26166c88 20#include "path-util.h"
25300b5a 21#include "process-util.h"
dc2c282b 22#include "pull-common.h"
07630cea 23#include "pull-job.h"
3ffd4af2 24#include "pull-tar.h"
07630cea
LP
25#include "rm-rf.h"
26#include "string-util.h"
27#include "strv.h"
e4de7287 28#include "tmpfile-util.h"
c40d82ab 29#include "user-util.h"
07630cea
LP
30#include "utf8.h"
31#include "util.h"
49cf4170 32#include "web-util.h"
56ebfaf1 33
7079cfef
LP
34typedef enum TarProgress {
35 TAR_DOWNLOADING,
36 TAR_VERIFYING,
37 TAR_FINALIZING,
38 TAR_COPYING,
39} TarProgress;
40
dc2c282b 41struct TarPull {
56ebfaf1
LP
42 sd_event *event;
43 CurlGlue *glue;
44
133b34f6
LP
45 PullFlags flags;
46 ImportVerify verify;
56ebfaf1
LP
47 char *image_root;
48
dc2c282b
LP
49 PullJob *tar_job;
50 PullJob *checksum_job;
51 PullJob *signature_job;
133b34f6 52 PullJob *settings_job;
56ebfaf1 53
dc2c282b 54 TarPullFinished on_finished;
56ebfaf1
LP
55 void *userdata;
56
56ebfaf1 57 char *local;
56ebfaf1
LP
58
59 pid_t tar_pid;
60
56ebfaf1 61 char *final_path;
9854730b
LP
62 char *temp_path;
63
64 char *settings_path;
65 char *settings_temp_path;
c40d82ab
LP
66
67 char *checksum;
56ebfaf1
LP
68};
69
dc2c282b 70TarPull* tar_pull_unref(TarPull *i) {
56ebfaf1
LP
71 if (!i)
72 return NULL;
73
0100b6e1 74 if (i->tar_pid > 1) {
8b71fce8 75 (void) kill_and_sigcont(i->tar_pid, SIGKILL);
0100b6e1 76 (void) wait_for_terminate(i->tar_pid, NULL);
56ebfaf1
LP
77 }
78
dc2c282b
LP
79 pull_job_unref(i->tar_job);
80 pull_job_unref(i->checksum_job);
81 pull_job_unref(i->signature_job);
133b34f6 82 pull_job_unref(i->settings_job);
56ebfaf1
LP
83
84 curl_glue_unref(i->glue);
85 sd_event_unref(i->event);
86
133b34f6
LP
87 rm_rf_subvolume_and_free(i->temp_path);
88 unlink_and_free(i->settings_temp_path);
9854730b 89
56ebfaf1 90 free(i->final_path);
9854730b 91 free(i->settings_path);
56ebfaf1
LP
92 free(i->image_root);
93 free(i->local);
c40d82ab 94 free(i->checksum);
e0061812 95
6b430fdb 96 return mfree(i);
56ebfaf1
LP
97}
98
dc2c282b
LP
99int tar_pull_new(
100 TarPull **ret,
8b71fce8
LP
101 sd_event *event,
102 const char *image_root,
dc2c282b 103 TarPullFinished on_finished,
8b71fce8
LP
104 void *userdata) {
105
0d94088e
YW
106 _cleanup_(curl_glue_unrefp) CurlGlue *g = NULL;
107 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
dc2c282b 108 _cleanup_(tar_pull_unrefp) TarPull *i = NULL;
0d94088e 109 _cleanup_free_ char *root = NULL;
56ebfaf1
LP
110 int r;
111
112 assert(ret);
56ebfaf1 113
0d94088e
YW
114 root = strdup(image_root ?: "/var/lib/machines");
115 if (!root)
56ebfaf1
LP
116 return -ENOMEM;
117
9854730b 118 if (event)
0d94088e 119 e = sd_event_ref(event);
9854730b 120 else {
0d94088e 121 r = sd_event_default(&e);
9854730b
LP
122 if (r < 0)
123 return r;
124 }
56ebfaf1 125
0d94088e 126 r = curl_glue_new(&g, e);
56ebfaf1
LP
127 if (r < 0)
128 return r;
129
0d94088e
YW
130 i = new(TarPull, 1);
131 if (!i)
132 return -ENOMEM;
133
134 *i = (TarPull) {
135 .on_finished = on_finished,
136 .userdata = userdata,
137 .image_root = TAKE_PTR(root),
0d94088e
YW
138 .event = TAKE_PTR(e),
139 .glue = TAKE_PTR(g),
140 };
141
dc2c282b 142 i->glue->on_finished = pull_job_curl_on_finished;
56ebfaf1
LP
143 i->glue->userdata = i;
144
1cc6c93a 145 *ret = TAKE_PTR(i);
56ebfaf1
LP
146
147 return 0;
148}
149
dc2c282b 150static void tar_pull_report_progress(TarPull *i, TarProgress p) {
7079cfef
LP
151 unsigned percent;
152
153 assert(i);
154
155 switch (p) {
156
157 case TAR_DOWNLOADING: {
158 unsigned remain = 85;
159
160 percent = 0;
161
162 if (i->checksum_job) {
163 percent += i->checksum_job->progress_percent * 5 / 100;
164 remain -= 5;
165 }
166
167 if (i->signature_job) {
168 percent += i->signature_job->progress_percent * 5 / 100;
169 remain -= 5;
170 }
171
133b34f6
LP
172 if (i->settings_job) {
173 percent += i->settings_job->progress_percent * 5 / 100;
174 remain -= 5;
175 }
176
7079cfef
LP
177 if (i->tar_job)
178 percent += i->tar_job->progress_percent * remain / 100;
179 break;
180 }
181
182 case TAR_VERIFYING:
183 percent = 85;
184 break;
185
186 case TAR_FINALIZING:
187 percent = 90;
188 break;
189
190 case TAR_COPYING:
191 percent = 95;
192 break;
193
194 default:
04499a70 195 assert_not_reached();
7079cfef
LP
196 }
197
198 sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
199 log_debug("Combined progress %u%%", percent);
200}
201
c40d82ab
LP
202static int tar_pull_determine_path(
203 TarPull *i,
204 const char *suffix,
205 char **field /* input + output (!) */) {
91359193
LP
206 int r;
207
208 assert(i);
209 assert(field);
210
211 if (*field)
212 return 0;
213
214 assert(i->tar_job);
215
216 r = pull_make_path(i->tar_job->url, i->tar_job->etag, i->image_root, ".tar-", suffix, field);
217 if (r < 0)
218 return log_oom();
219
220 return 1;
221}
222
dc2c282b 223static int tar_pull_make_local_copy(TarPull *i) {
c40d82ab
LP
224 _cleanup_(rm_rf_subvolume_and_freep) char *t = NULL;
225 const char *p;
0d6e763b
LP
226 int r;
227
228 assert(i);
229 assert(i->tar_job);
230
231 if (!i->local)
232 return 0;
233
c40d82ab
LP
234 assert(i->final_path);
235
236 p = prefix_roota(i->image_root, i->local);
237
238 r = tempfn_random(p, NULL, &t);
0100b6e1 239 if (r < 0)
c40d82ab
LP
240 return log_error_errno(r, "Failed to generate temporary filename for %s: %m", p);
241
242 if (i->flags & PULL_BTRFS_SUBVOL)
243 r = btrfs_subvol_snapshot(
244 i->final_path,
245 t,
246 (i->flags & PULL_BTRFS_QUOTA ? BTRFS_SNAPSHOT_QUOTA : 0)|
247 BTRFS_SNAPSHOT_FALLBACK_COPY|
248 BTRFS_SNAPSHOT_FALLBACK_DIRECTORY|
249 BTRFS_SNAPSHOT_RECURSIVE);
250 else
251 r = copy_tree(i->final_path, t, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_HARDLINKS);
252 if (r < 0)
253 return log_error_errno(r, "Failed to create local image: %m");
254
255 r = install_file(AT_FDCWD, t,
256 AT_FDCWD, p,
257 (i->flags & PULL_FORCE ? INSTALL_REPLACE : 0) |
258 (i->flags & PULL_READ_ONLY ? INSTALL_READ_ONLY : 0) |
259 (i->flags & PULL_SYNC ? INSTALL_SYNCFS : 0));
260 if (r < 0)
261 return log_error_errno(r, "Failed to install local image '%s': %m", p);
262
263 t = mfree(t);
264
265 log_info("Created new local image '%s'.", i->local);
0100b6e1 266
133b34f6 267 if (FLAGS_SET(i->flags, PULL_SETTINGS)) {
9854730b
LP
268 const char *local_settings;
269 assert(i->settings_job);
270
91359193
LP
271 r = tar_pull_determine_path(i, ".nspawn", &i->settings_path);
272 if (r < 0)
273 return r;
9854730b
LP
274
275 local_settings = strjoina(i->image_root, "/", i->local, ".nspawn");
276
c40d82ab
LP
277 r = copy_file_atomic(
278 i->settings_path,
279 local_settings,
280 0664,
281 0, 0,
282 COPY_REFLINK |
283 (FLAGS_SET(i->flags, PULL_FORCE) ? COPY_REPLACE : 0) |
284 (FLAGS_SET(i->flags, PULL_SYNC) ? COPY_FSYNC_FULL : 0));
9854730b
LP
285 if (r == -EEXIST)
286 log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings);
33859a6b
LP
287 else if (r == -ENOENT)
288 log_debug_errno(r, "Skipping creation of settings file, since none was found.");
289 else if (r < 0)
79b6198b
LP
290 log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings);
291 else
33859a6b 292 log_info("Created new settings file %s.", local_settings);
9854730b
LP
293 }
294
0d6e763b
LP
295 return 0;
296}
297
dc2c282b 298static bool tar_pull_is_done(TarPull *i) {
8b71fce8
LP
299 assert(i);
300 assert(i->tar_job);
301
9854730b 302 if (!PULL_JOB_IS_COMPLETE(i->tar_job))
8b71fce8 303 return false;
9854730b
LP
304 if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job))
305 return false;
306 if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job))
8b71fce8 307 return false;
133b34f6
LP
308 if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job))
309 return false;
8b71fce8
LP
310
311 return true;
312}
313
dc2c282b
LP
314static void tar_pull_job_on_finished(PullJob *j) {
315 TarPull *i;
56ebfaf1
LP
316 int r;
317
318 assert(j);
319 assert(j->userdata);
320
321 i = j->userdata;
9854730b 322
c40d82ab
LP
323 if (j->error != 0) {
324 if (j == i->tar_job) {
325 if (j->error == ENOMEDIUM) /* HTTP 404 */
326 r = log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)");
327 else
328 r = log_error_errno(j->error, "Failed to retrieve image file.");
329 goto finish;
330 } else if (j == i->checksum_job) {
331 r = log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
332 goto finish;
333 } else if (j == i->signature_job)
334 log_debug_errno(j->error, "Signature job for %s failed, proceeding for now.", j->url);
335 else if (j == i->settings_job)
9854730b 336 log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
0100b6e1 337 else
c40d82ab 338 assert("unexpected job");
56ebfaf1
LP
339 }
340
c33e405f
LP
341 /* This is invoked if either the download completed successfully, or the download was skipped because
342 * we already have the etag. */
56ebfaf1 343
dc2c282b 344 if (!tar_pull_is_done(i))
0100b6e1
LP
345 return;
346
f14717a7
LP
347 if (i->signature_job && i->signature_job->error != 0) {
348 VerificationStyle style;
697be0be 349
c40d82ab
LP
350 assert(i->checksum_job);
351
f14717a7
LP
352 r = verification_style_from_url(i->checksum_job->url, &style);
353 if (r < 0) {
354 log_error_errno(r, "Failed to determine verification style from checksum URL: %m");
355 goto finish;
356 }
357
358 if (style == VERIFICATION_PER_DIRECTORY) { /* A failed signature file download only matters
359 * in per-directory verification mode, since only
360 * then the signature is detached, and thus a file
361 * of its own. */
c40d82ab
LP
362 r = log_error_errno(i->signature_job->error,
363 "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
f14717a7
LP
364 goto finish;
365 }
697be0be
TB
366 }
367
c40d82ab
LP
368 pull_job_close_disk_fd(i->tar_job);
369 pull_job_close_disk_fd(i->settings_job);
91359193 370
56ebfaf1 371 if (i->tar_pid > 0) {
7d4904fe 372 r = wait_for_terminate_and_check("tar", i->tar_pid, WAIT_LOG);
56ebfaf1
LP
373 i->tar_pid = 0;
374 if (r < 0)
375 goto finish;
b4a34311 376 if (r != EXIT_SUCCESS) {
9854730b
LP
377 r = -EIO;
378 goto finish;
379 }
56ebfaf1
LP
380 }
381
0100b6e1
LP
382 if (!i->tar_job->etag_exists) {
383 /* This is a new download, verify it, and move it into place */
384
dc2c282b 385 tar_pull_report_progress(i, TAR_VERIFYING);
7079cfef 386
ff2f7797 387 r = pull_verify(i->verify,
c40d82ab 388 i->checksum,
ff2f7797
LP
389 i->tar_job,
390 i->checksum_job,
391 i->signature_job,
392 i->settings_job,
393 /* roothash_job = */ NULL,
394 /* roothash_signature_job = */ NULL,
395 /* verity_job = */ NULL);
0100b6e1
LP
396 if (r < 0)
397 goto finish;
c40d82ab 398 }
0100b6e1 399
c40d82ab
LP
400 if (i->flags & PULL_DIRECT) {
401 assert(!i->settings_job);
402 assert(i->local);
403 assert(!i->temp_path);
7079cfef 404
c40d82ab 405 tar_pull_report_progress(i, TAR_FINALIZING);
c33e405f 406
c40d82ab 407 r = import_mangle_os_tree(i->local);
56ebfaf1
LP
408 if (r < 0)
409 goto finish;
410
c40d82ab
LP
411 r = install_file(
412 AT_FDCWD, i->local,
413 AT_FDCWD, NULL,
414 (i->flags & PULL_READ_ONLY) ? INSTALL_READ_ONLY : 0 |
415 (i->flags & PULL_SYNC ? INSTALL_SYNCFS : 0));
f85ef957 416 if (r < 0) {
c40d82ab 417 log_error_errno(r, "Failed to finalize '%s': %m", i->local);
56ebfaf1
LP
418 goto finish;
419 }
c40d82ab
LP
420 } else {
421 r = tar_pull_determine_path(i, NULL, &i->final_path);
422 if (r < 0)
423 goto finish;
56ebfaf1 424
c40d82ab
LP
425 if (!i->tar_job->etag_exists) {
426 /* This is a new download, verify it, and move it into place */
9854730b 427
c40d82ab
LP
428 assert(i->temp_path);
429 assert(i->final_path);
91359193 430
c40d82ab 431 tar_pull_report_progress(i, TAR_FINALIZING);
e0061812 432
c40d82ab 433 r = import_mangle_os_tree(i->temp_path);
91359193
LP
434 if (r < 0)
435 goto finish;
9854730b 436
c40d82ab
LP
437 r = install_file(
438 AT_FDCWD, i->temp_path,
439 AT_FDCWD, i->final_path,
440 INSTALL_READ_ONLY|
441 (i->flags & PULL_SYNC ? INSTALL_SYNCFS : 0));
9854730b 442 if (r < 0) {
c40d82ab 443 log_error_errno(r, "Failed to rename to final image name to %s: %m", i->final_path);
9854730b
LP
444 goto finish;
445 }
446
c40d82ab
LP
447 i->temp_path = mfree(i->temp_path);
448
449 if (i->settings_job &&
450 i->settings_job->error == 0) {
451
452 /* Also move the settings file into place, if it exists. Note that we do so only if we also
453 * moved the tar file in place, to keep things strictly in sync. */
454 assert(i->settings_temp_path);
455
456 /* Regenerate final name for this auxiliary file, we might know the etag of the file now, and
457 * we should incorporate it in the file name if we can */
458 i->settings_path = mfree(i->settings_path);
459
460 r = tar_pull_determine_path(i, ".nspawn", &i->settings_path);
461 if (r < 0)
462 goto finish;
463
464 r = install_file(
465 AT_FDCWD, i->settings_temp_path,
466 AT_FDCWD, i->settings_path,
467 INSTALL_READ_ONLY|
468 (i->flags & PULL_SYNC ? INSTALL_FSYNC_FULL : 0));
469 if (r < 0) {
470 log_error_errno(r, "Failed to rename settings file to %s: %m", i->settings_path);
471 goto finish;
472 }
473
474 i->settings_temp_path = mfree(i->settings_temp_path);
475 }
9854730b 476 }
56ebfaf1 477
c40d82ab 478 tar_pull_report_progress(i, TAR_COPYING);
7079cfef 479
c40d82ab
LP
480 r = tar_pull_make_local_copy(i);
481 if (r < 0)
482 goto finish;
483 }
0d6e763b 484
56ebfaf1
LP
485 r = 0;
486
487finish:
56ebfaf1
LP
488 if (i->on_finished)
489 i->on_finished(i, r, i->userdata);
490 else
491 sd_event_exit(i->event, r);
492}
493
9854730b 494static int tar_pull_job_on_open_disk_tar(PullJob *j) {
c40d82ab 495 const char *where;
dc2c282b 496 TarPull *i;
56ebfaf1
LP
497 int r;
498
499 assert(j);
500 assert(j->userdata);
501
502 i = j->userdata;
8b71fce8 503 assert(i->tar_job == j);
8b71fce8 504 assert(i->tar_pid <= 0);
56ebfaf1 505
c40d82ab
LP
506 if (i->flags & PULL_DIRECT)
507 where = i->local;
508 else {
509 if (!i->temp_path) {
510 r = tempfn_random_child(i->image_root, "tar", &i->temp_path);
511 if (r < 0)
512 return log_oom();
513 }
514
515 where = i->temp_path;
91359193 516 }
56ebfaf1 517
c40d82ab
LP
518 (void) mkdir_parents_label(where, 0700);
519
520 if (FLAGS_SET(i->flags, PULL_DIRECT|PULL_FORCE))
521 (void) rm_rf(where, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
56ebfaf1 522
c40d82ab
LP
523 if (i->flags & PULL_BTRFS_SUBVOL)
524 r = btrfs_subvol_make_fallback(where, 0755);
525 else
526 r = mkdir(where, 0755) < 0 ? -errno : 0;
527 if (r == -EEXIST && (i->flags & PULL_DIRECT)) /* EEXIST is OK if in direct mode, but not otherwise,
528 * because in that case our temporary path collided */
529 r = 0;
82c4440d 530 if (r < 0)
c40d82ab
LP
531 return log_error_errno(r, "Failed to create directory/subvolume %s: %m", where);
532 if (r > 0 && (i->flags & PULL_BTRFS_QUOTA)) { /* actually btrfs subvol */
533 if (!(i->flags & PULL_DIRECT))
534 (void) import_assign_pool_quota_and_warn(i->image_root);
535 (void) import_assign_pool_quota_and_warn(where);
052ba0eb 536 }
56ebfaf1 537
c40d82ab 538 j->disk_fd = import_fork_tar_x(where, &i->tar_pid);
2c140ded
LP
539 if (j->disk_fd < 0)
540 return j->disk_fd;
56ebfaf1
LP
541
542 return 0;
543}
544
9854730b
LP
545static int tar_pull_job_on_open_disk_settings(PullJob *j) {
546 TarPull *i;
547 int r;
548
549 assert(j);
550 assert(j->userdata);
551
552 i = j->userdata;
553 assert(i->settings_job == j);
9854730b 554
91359193
LP
555 if (!i->settings_temp_path) {
556 r = tempfn_random_child(i->image_root, "settings", &i->settings_temp_path);
557 if (r < 0)
558 return log_oom();
559 }
9854730b 560
c40d82ab 561 (void) mkdir_parents_label(i->settings_temp_path, 0700);
9854730b
LP
562
563 j->disk_fd = open(i->settings_temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
564 if (j->disk_fd < 0)
565 return log_error_errno(errno, "Failed to create %s: %m", i->settings_temp_path);
566
567 return 0;
568}
569
dc2c282b
LP
570static void tar_pull_job_on_progress(PullJob *j) {
571 TarPull *i;
7079cfef
LP
572
573 assert(j);
574 assert(j->userdata);
575
576 i = j->userdata;
577
dc2c282b 578 tar_pull_report_progress(i, TAR_DOWNLOADING);
7079cfef
LP
579}
580
9854730b
LP
581int tar_pull_start(
582 TarPull *i,
583 const char *url,
584 const char *local,
133b34f6 585 PullFlags flags,
c40d82ab
LP
586 ImportVerify verify,
587 const char *checksum) {
9854730b 588
c40d82ab 589 PullJob *j;
56ebfaf1
LP
590 int r;
591
592 assert(i);
c40d82ab
LP
593 assert(verify == _IMPORT_VERIFY_INVALID || verify < _IMPORT_VERIFY_MAX);
594 assert(verify == _IMPORT_VERIFY_INVALID || verify >= 0);
595 assert((verify < 0) || !checksum);
133b34f6 596 assert(!(flags & ~PULL_FLAGS_MASK_TAR));
c40d82ab
LP
597 assert(!(flags & PULL_SETTINGS) || !(flags & PULL_DIRECT));
598 assert(!(flags & PULL_SETTINGS) || !checksum);
56ebfaf1 599
c456862f 600 if (!http_url_is_valid(url) && !file_url_is_valid(url))
56ebfaf1
LP
601 return -EINVAL;
602
c40d82ab 603 if (local && !pull_validate_local(local, flags))
56ebfaf1
LP
604 return -EINVAL;
605
8b71fce8
LP
606 if (i->tar_job)
607 return -EBUSY;
608
56ebfaf1
LP
609 r = free_and_strdup(&i->local, local);
610 if (r < 0)
611 return r;
9854730b 612
c40d82ab
LP
613 r = free_and_strdup(&i->checksum, checksum);
614 if (r < 0)
615 return r;
616
133b34f6 617 i->flags = flags;
0100b6e1 618 i->verify = verify;
56ebfaf1 619
9854730b 620 /* Set up download job for TAR file */
dc2c282b 621 r = pull_job_new(&i->tar_job, url, i->glue, i);
56ebfaf1
LP
622 if (r < 0)
623 return r;
624
dc2c282b 625 i->tar_job->on_finished = tar_pull_job_on_finished;
9854730b 626 i->tar_job->on_open_disk = tar_pull_job_on_open_disk_tar;
c40d82ab 627 i->tar_job->calc_checksum = checksum || IN_SET(verify, IMPORT_VERIFY_CHECKSUM, IMPORT_VERIFY_SIGNATURE);
56ebfaf1 628
c40d82ab
LP
629 if (!FLAGS_SET(flags, PULL_DIRECT)) {
630 r = pull_find_old_etags(url, i->image_root, DT_DIR, ".tar-", NULL, &i->tar_job->old_etags);
631 if (r < 0)
632 return r;
633 }
56ebfaf1 634
133b34f6 635 /* Set up download of checksum/signature files */
c40d82ab
LP
636 r = pull_make_verification_jobs(
637 &i->checksum_job,
638 &i->signature_job,
639 verify,
640 checksum,
641 url,
642 i->glue,
643 tar_pull_job_on_finished,
644 i);
133b34f6
LP
645 if (r < 0)
646 return r;
647
9854730b 648 /* Set up download job for the settings file (.nspawn) */
133b34f6 649 if (FLAGS_SET(flags, PULL_SETTINGS)) {
c40d82ab
LP
650 r = pull_make_auxiliary_job(
651 &i->settings_job,
652 url,
653 tar_strip_suffixes,
654 ".nspawn",
655 verify,
656 i->glue,
657 tar_pull_job_on_open_disk_settings,
658 tar_pull_job_on_finished,
659 i);
9854730b
LP
660 if (r < 0)
661 return r;
9854730b
LP
662 }
663
c40d82ab
LP
664 FOREACH_POINTER(j,
665 i->tar_job,
666 i->checksum_job,
667 i->signature_job,
668 i->settings_job) {
0100b6e1 669
c40d82ab
LP
670 if (!j)
671 continue;
7079cfef 672
c40d82ab
LP
673 j->on_progress = tar_pull_job_on_progress;
674 j->sync = FLAGS_SET(flags, PULL_SYNC);
0100b6e1 675
c40d82ab 676 r = pull_job_begin(j);
133b34f6
LP
677 if (r < 0)
678 return r;
679 }
680
0100b6e1 681 return 0;
56ebfaf1 682}