]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/import/pull-raw.c
Merge pull request #17549 from yuwata/tiny-fixes
[thirdparty/systemd.git] / src / import / pull-raw.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
90199220 2
90199220 3#include <curl/curl.h>
07630cea
LP
4#include <linux/fs.h>
5#include <sys/xattr.h>
90199220 6
7079cfef 7#include "sd-daemon.h"
07630cea 8
b5efdb8a 9#include "alloc-util.h"
0d6e763b 10#include "btrfs-util.h"
07630cea
LP
11#include "copy.h"
12#include "curl-util.h"
3ffd4af2 13#include "fd-util.h"
f4f15635 14#include "fs-util.h"
07630cea
LP
15#include "hostname-util.h"
16#include "import-common.h"
17#include "import-util.h"
0d6e763b
LP
18#include "macro.h"
19#include "mkdir.h"
26166c88 20#include "path-util.h"
dc2c282b 21#include "pull-common.h"
07630cea 22#include "pull-job.h"
3ffd4af2 23#include "pull-raw.h"
07630cea
LP
24#include "qcow2-util.h"
25#include "rm-rf.h"
26#include "string-util.h"
27#include "strv.h"
e4de7287 28#include "tmpfile-util.h"
07630cea
LP
29#include "utf8.h"
30#include "util.h"
49cf4170 31#include "web-util.h"
90199220 32
7079cfef
LP
33typedef enum RawProgress {
34 RAW_DOWNLOADING,
35 RAW_VERIFYING,
36 RAW_UNPACKING,
37 RAW_FINALIZING,
38 RAW_COPYING,
39} RawProgress;
90199220 40
dc2c282b 41struct RawPull {
90199220
LP
42 sd_event *event;
43 CurlGlue *glue;
44
087682d1 45 char *image_root;
90199220 46
dc2c282b 47 PullJob *raw_job;
91359193 48 PullJob *roothash_job;
9854730b 49 PullJob *settings_job;
dc2c282b
LP
50 PullJob *checksum_job;
51 PullJob *signature_job;
90199220 52
dc2c282b 53 RawPullFinished on_finished;
0d6e763b 54 void *userdata;
90199220 55
0d6e763b
LP
56 char *local;
57 bool force_local;
9854730b 58 bool settings;
91359193 59 bool roothash;
8620a9a3 60
0d6e763b 61 char *final_path;
9854730b
LP
62 char *temp_path;
63
64 char *settings_path;
65 char *settings_temp_path;
8f695058 66
91359193
LP
67 char *roothash_path;
68 char *roothash_temp_path;
69
8f695058 70 ImportVerify verify;
0d6e763b 71};
49bb233b 72
dc2c282b 73RawPull* raw_pull_unref(RawPull *i) {
0d6e763b 74 if (!i)
90199220
LP
75 return NULL;
76
dc2c282b 77 pull_job_unref(i->raw_job);
9854730b 78 pull_job_unref(i->settings_job);
91359193 79 pull_job_unref(i->roothash_job);
dc2c282b
LP
80 pull_job_unref(i->checksum_job);
81 pull_job_unref(i->signature_job);
90199220 82
0d6e763b
LP
83 curl_glue_unref(i->glue);
84 sd_event_unref(i->event);
90199220 85
0d6e763b
LP
86 if (i->temp_path) {
87 (void) unlink(i->temp_path);
88 free(i->temp_path);
90199220
LP
89 }
90
91359193
LP
91 if (i->roothash_temp_path) {
92 (void) unlink(i->roothash_temp_path);
93 free(i->roothash_temp_path);
94 }
95
9854730b
LP
96 if (i->settings_temp_path) {
97 (void) unlink(i->settings_temp_path);
98 free(i->settings_temp_path);
99 }
100
0d6e763b 101 free(i->final_path);
91359193 102 free(i->roothash_path);
9854730b 103 free(i->settings_path);
0d6e763b
LP
104 free(i->image_root);
105 free(i->local);
6b430fdb 106 return mfree(i);
90199220
LP
107}
108
dc2c282b
LP
109int raw_pull_new(
110 RawPull **ret,
8b71fce8
LP
111 sd_event *event,
112 const char *image_root,
dc2c282b 113 RawPullFinished on_finished,
8b71fce8
LP
114 void *userdata) {
115
0d94088e
YW
116 _cleanup_(curl_glue_unrefp) CurlGlue *g = NULL;
117 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
dc2c282b 118 _cleanup_(raw_pull_unrefp) RawPull *i = NULL;
0d94088e 119 _cleanup_free_ char *root = NULL;
0d6e763b 120 int r;
8620a9a3 121
0d6e763b 122 assert(ret);
8620a9a3 123
0d94088e
YW
124 root = strdup(image_root ?: "/var/lib/machines");
125 if (!root)
8620a9a3
LP
126 return -ENOMEM;
127
0d6e763b 128 if (event)
0d94088e 129 e = sd_event_ref(event);
0d6e763b 130 else {
0d94088e 131 r = sd_event_default(&e);
dfd1520d 132 if (r < 0)
0d6e763b 133 return r;
2f64ba0e 134 }
8620a9a3 135
0d94088e 136 r = curl_glue_new(&g, e);
2f64ba0e 137 if (r < 0)
0d6e763b 138 return r;
8620a9a3 139
0d94088e
YW
140 i = new(RawPull, 1);
141 if (!i)
142 return -ENOMEM;
143
144 *i = (RawPull) {
145 .on_finished = on_finished,
146 .userdata = userdata,
147 .image_root = TAKE_PTR(root),
0d94088e
YW
148 .event = TAKE_PTR(e),
149 .glue = TAKE_PTR(g),
150 };
151
dc2c282b 152 i->glue->on_finished = pull_job_curl_on_finished;
0d6e763b 153 i->glue->userdata = i;
8620a9a3 154
1cc6c93a 155 *ret = TAKE_PTR(i);
8620a9a3 156
2f64ba0e
LP
157 return 0;
158}
159
dc2c282b 160static void raw_pull_report_progress(RawPull *i, RawProgress p) {
7079cfef
LP
161 unsigned percent;
162
163 assert(i);
164
165 switch (p) {
166
167 case RAW_DOWNLOADING: {
168 unsigned remain = 80;
169
170 percent = 0;
171
9854730b
LP
172 if (i->settings_job) {
173 percent += i->settings_job->progress_percent * 5 / 100;
174 remain -= 5;
175 }
176
91359193
LP
177 if (i->roothash_job) {
178 percent += i->roothash_job->progress_percent * 5 / 100;
179 remain -= 5;
180 }
181
7079cfef
LP
182 if (i->checksum_job) {
183 percent += i->checksum_job->progress_percent * 5 / 100;
184 remain -= 5;
185 }
186
187 if (i->signature_job) {
188 percent += i->signature_job->progress_percent * 5 / 100;
189 remain -= 5;
190 }
191
192 if (i->raw_job)
193 percent += i->raw_job->progress_percent * remain / 100;
194 break;
195 }
196
197 case RAW_VERIFYING:
198 percent = 80;
199 break;
200
201 case RAW_UNPACKING:
202 percent = 85;
203 break;
204
205 case RAW_FINALIZING:
206 percent = 90;
207 break;
208
209 case RAW_COPYING:
210 percent = 95;
211 break;
212
213 default:
214 assert_not_reached("Unknown progress state");
215 }
216
217 sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
218 log_debug("Combined progress %u%%", percent);
219}
220
dc2c282b 221static int raw_pull_maybe_convert_qcow2(RawPull *i) {
edce2aed
LP
222 _cleanup_close_ int converted_fd = -1;
223 _cleanup_free_ char *t = NULL;
224 int r;
225
0d6e763b
LP
226 assert(i);
227 assert(i->raw_job);
edce2aed 228
0d6e763b 229 r = qcow2_detect(i->raw_job->disk_fd);
edce2aed
LP
230 if (r < 0)
231 return log_error_errno(r, "Failed to detect whether this is a QCOW2 image: %m");
232 if (r == 0)
233 return 0;
234
235 /* This is a QCOW2 image, let's convert it */
14bcf25c 236 r = tempfn_random(i->final_path, NULL, &t);
edce2aed
LP
237 if (r < 0)
238 return log_oom();
239
b6e676ce 240 converted_fd = open(t, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
edce2aed
LP
241 if (converted_fd < 0)
242 return log_error_errno(errno, "Failed to create %s: %m", t);
243
137c6c6b 244 (void) import_set_nocow_and_log(converted_fd, t);
0d6e763b 245
ec5cb56e
LP
246 log_info("Unpacking QCOW2 file.");
247
0d6e763b 248 r = qcow2_convert(i->raw_job->disk_fd, converted_fd);
edce2aed 249 if (r < 0) {
6990fb6b 250 (void) unlink(t);
edce2aed
LP
251 return log_error_errno(r, "Failed to convert qcow2 image: %m");
252 }
253
b6e676ce 254 (void) unlink(i->temp_path);
f9ecfd3b 255 free_and_replace(i->temp_path, t);
0706c012 256 CLOSE_AND_REPLACE(i->raw_job->disk_fd, converted_fd);
edce2aed
LP
257
258 return 1;
259}
260
91359193
LP
261static int raw_pull_determine_path(RawPull *i, const char *suffix, char **field) {
262 int r;
263
264 assert(i);
265 assert(field);
266
267 if (*field)
268 return 0;
269
270 assert(i->raw_job);
271
272 r = pull_make_path(i->raw_job->url, i->raw_job->etag, i->image_root, ".raw-", suffix, field);
273 if (r < 0)
274 return log_oom();
275
276 return 1;
277}
278
279static int raw_pull_copy_auxiliary_file(
280 RawPull *i,
281 const char *suffix,
282 char **path) {
283
284 const char *local;
285 int r;
286
287 assert(i);
288 assert(suffix);
289 assert(path);
290
291 r = raw_pull_determine_path(i, suffix, path);
292 if (r < 0)
293 return r;
294
295 local = strjoina(i->image_root, "/", i->local, suffix);
296
8a016c74 297 r = copy_file_atomic(*path, local, 0644, 0, 0, COPY_REFLINK | (i->force_local ? COPY_REPLACE : 0));
91359193
LP
298 if (r == -EEXIST)
299 log_warning_errno(r, "File %s already exists, not replacing.", local);
300 else if (r == -ENOENT)
301 log_debug_errno(r, "Skipping creation of auxiliary file, since none was found.");
302 else if (r < 0)
303 log_warning_errno(r, "Failed to copy file %s, ignoring: %m", local);
304 else
305 log_info("Created new file %s.", local);
306
307 return 0;
308}
309
dc2c282b 310static int raw_pull_make_local_copy(RawPull *i) {
0d6e763b
LP
311 _cleanup_free_ char *tp = NULL;
312 _cleanup_close_ int dfd = -1;
313 const char *p;
90199220
LP
314 int r;
315
0d6e763b
LP
316 assert(i);
317 assert(i->raw_job);
90199220 318
0d6e763b 319 if (!i->local)
90199220
LP
320 return 0;
321
85dbc41d
LP
322 if (i->raw_job->etag_exists) {
323 /* We have downloaded this one previously, reopen it */
324
325 assert(i->raw_job->disk_fd < 0);
326
0d6e763b
LP
327 i->raw_job->disk_fd = open(i->final_path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
328 if (i->raw_job->disk_fd < 0)
329 return log_error_errno(errno, "Failed to open vendor image: %m");
85dbc41d
LP
330 } else {
331 /* We freshly downloaded the image, use it */
332
333 assert(i->raw_job->disk_fd >= 0);
334
335 if (lseek(i->raw_job->disk_fd, SEEK_SET, 0) == (off_t) -1)
336 return log_error_errno(errno, "Failed to seek to beginning of vendor image: %m");
90199220
LP
337 }
338
63c372cb 339 p = strjoina(i->image_root, "/", i->local, ".raw");
49bb233b 340
d9e2daaf
LP
341 if (i->force_local)
342 (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
49bb233b 343
14bcf25c 344 r = tempfn_random(p, NULL, &tp);
49bb233b 345 if (r < 0)
0d6e763b 346 return log_oom();
49bb233b 347
0d6e763b
LP
348 dfd = open(tp, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
349 if (dfd < 0)
350 return log_error_errno(errno, "Failed to create writable copy of image: %m");
49bb233b 351
137c6c6b
LP
352 /* Turn off COW writing. This should greatly improve performance on COW file systems like btrfs,
353 * since it reduces fragmentation caused by not allowing in-place writes. */
354 (void) import_set_nocow_and_log(dfd, tp);
90199220 355
1c876927 356 r = copy_bytes(i->raw_job->disk_fd, dfd, (uint64_t) -1, COPY_REFLINK);
90199220 357 if (r < 0) {
6990fb6b 358 (void) unlink(tp);
0d6e763b 359 return log_error_errno(r, "Failed to make writable copy of image: %m");
90199220
LP
360 }
361
adc6f43b 362 (void) copy_times(i->raw_job->disk_fd, dfd, COPY_CRTIME);
0d6e763b 363 (void) copy_xattr(i->raw_job->disk_fd, dfd);
1e20b411 364
0d6e763b 365 dfd = safe_close(dfd);
1e20b411 366
0d6e763b
LP
367 r = rename(tp, p);
368 if (r < 0) {
5cfab271 369 r = log_error_errno(errno, "Failed to move writable image into place: %m");
6990fb6b 370 (void) unlink(tp);
5cfab271 371 return r;
1e20b411
LP
372 }
373
0d6e763b 374 log_info("Created new local image '%s'.", i->local);
9854730b 375
91359193
LP
376 if (i->roothash) {
377 r = raw_pull_copy_auxiliary_file(i, ".roothash", &i->roothash_path);
378 if (r < 0)
379 return r;
380 }
9854730b 381
91359193
LP
382 if (i->settings) {
383 r = raw_pull_copy_auxiliary_file(i, ".nspawn", &i->settings_path);
384 if (r < 0)
385 return r;
9854730b
LP
386 }
387
1e20b411
LP
388 return 0;
389}
390
dc2c282b 391static bool raw_pull_is_done(RawPull *i) {
8b71fce8
LP
392 assert(i);
393 assert(i->raw_job);
394
9854730b 395 if (!PULL_JOB_IS_COMPLETE(i->raw_job))
8b71fce8 396 return false;
91359193
LP
397 if (i->roothash_job && !PULL_JOB_IS_COMPLETE(i->roothash_job))
398 return false;
9854730b 399 if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job))
8b71fce8 400 return false;
9854730b
LP
401 if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job))
402 return false;
403 if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job))
8b71fce8
LP
404 return false;
405
406 return true;
407}
408
91359193
LP
409static int raw_pull_rename_auxiliary_file(
410 RawPull *i,
411 const char *suffix,
412 char **temp_path,
413 char **path) {
414
415 int r;
416
417 assert(i);
418 assert(temp_path);
419 assert(suffix);
420 assert(path);
421
e0061812 422 /* Regenerate final name for this auxiliary file, we might know the etag of the file now, and we should
91359193
LP
423 * incorporate it in the file name if we can */
424 *path = mfree(*path);
425 r = raw_pull_determine_path(i, suffix, path);
426 if (r < 0)
427 return r;
428
429 r = import_make_read_only(*temp_path);
430 if (r < 0)
431 return r;
432
433 r = rename_noreplace(AT_FDCWD, *temp_path, AT_FDCWD, *path);
434 if (r < 0)
435 return log_error_errno(r, "Failed to rename file %s to %s: %m", *temp_path, *path);
436
437 *temp_path = mfree(*temp_path);
438
439 return 1;
440}
441
dc2c282b
LP
442static void raw_pull_job_on_finished(PullJob *j) {
443 RawPull *i;
8620a9a3
LP
444 int r;
445
0d6e763b
LP
446 assert(j);
447 assert(j->userdata);
8620a9a3 448
0d6e763b 449 i = j->userdata;
91359193
LP
450 if (j == i->roothash_job) {
451 if (j->error != 0)
452 log_info_errno(j->error, "Root hash file could not be retrieved, proceeding without.");
453 } else if (j == i->settings_job) {
9854730b
LP
454 if (j->error != 0)
455 log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
697be0be 456 } else if (j->error != 0 && j != i->signature_job) {
98c38001 457 if (j == i->checksum_job)
3576d631 458 log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
3576d631
LP
459 else
460 log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)");
461
0d6e763b
LP
462 r = j->error;
463 goto finish;
8620a9a3
LP
464 }
465
0d6e763b
LP
466 /* This is invoked if either the download completed
467 * successfully, or the download was skipped because we
85dbc41d 468 * already have the etag. In this case ->etag_exists is
3576d631
LP
469 * true.
470 *
471 * We only do something when we got all three files */
85dbc41d 472
dc2c282b 473 if (!raw_pull_is_done(i))
3576d631 474 return;
8620a9a3 475
c9fb8c7c 476 if (i->signature_job && i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) {
697be0be
TB
477 log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
478
479 r = i->signature_job->error;
480 goto finish;
481 }
482
91359193
LP
483 if (i->roothash_job)
484 i->roothash_job->disk_fd = safe_close(i->roothash_job->disk_fd);
9854730b
LP
485 if (i->settings_job)
486 i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd);
487
91359193
LP
488 r = raw_pull_determine_path(i, ".raw", &i->final_path);
489 if (r < 0)
490 goto finish;
491
3576d631 492 if (!i->raw_job->etag_exists) {
98c38001 493 /* This is a new download, verify it, and move it into place */
3576d631
LP
494 assert(i->raw_job->disk_fd >= 0);
495
dc2c282b 496 raw_pull_report_progress(i, RAW_VERIFYING);
7079cfef 497
91359193 498 r = pull_verify(i->raw_job, i->roothash_job, i->settings_job, i->checksum_job, i->signature_job);
0d6e763b
LP
499 if (r < 0)
500 goto finish;
8620a9a3 501
dc2c282b 502 raw_pull_report_progress(i, RAW_UNPACKING);
7079cfef 503
dc2c282b 504 r = raw_pull_maybe_convert_qcow2(i);
0d6e763b
LP
505 if (r < 0)
506 goto finish;
85dbc41d 507
dc2c282b 508 raw_pull_report_progress(i, RAW_FINALIZING);
7079cfef 509
50dfca2e
KK
510 if (i->raw_job->etag) {
511 /* Only make a read-only copy if ETag header is set. */
512 r = import_make_read_only_fd(i->raw_job->disk_fd);
513 if (r < 0)
514 goto finish;
515
516 r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
517 if (r < 0) {
518 log_error_errno(r, "Failed to rename raw file to %s: %m", i->final_path);
519 goto finish;
520 }
3576d631 521 }
8f695058 522
9854730b
LP
523 i->temp_path = mfree(i->temp_path);
524
91359193
LP
525 if (i->roothash_job &&
526 i->roothash_job->error == 0) {
527 r = raw_pull_rename_auxiliary_file(i, ".roothash", &i->roothash_temp_path, &i->roothash_path);
9854730b
LP
528 if (r < 0)
529 goto finish;
91359193 530 }
9854730b 531
91359193
LP
532 if (i->settings_job &&
533 i->settings_job->error == 0) {
534 r = raw_pull_rename_auxiliary_file(i, ".nspawn", &i->settings_temp_path, &i->settings_path);
535 if (r < 0)
9854730b 536 goto finish;
9854730b 537 }
8620a9a3
LP
538 }
539
dc2c282b 540 raw_pull_report_progress(i, RAW_COPYING);
7079cfef 541
dc2c282b 542 r = raw_pull_make_local_copy(i);
8620a9a3 543 if (r < 0)
0d6e763b 544 goto finish;
90199220 545
0d6e763b 546 r = 0;
3576d631 547
0d6e763b 548finish:
3576d631
LP
549 if (i->on_finished)
550 i->on_finished(i, r, i->userdata);
551 else
552 sd_event_exit(i->event, r);
0d6e763b 553}
90199220 554
91359193
LP
555static int raw_pull_job_on_open_disk_generic(
556 RawPull *i,
557 PullJob *j,
558 const char *extra,
559 char **temp_path) {
560
91359193
LP
561 int r;
562
563 assert(i);
564 assert(j);
565 assert(extra);
566 assert(temp_path);
567
568 if (!*temp_path) {
569 r = tempfn_random_child(i->image_root, extra, temp_path);
570 if (r < 0)
571 return log_oom();
572 }
573
574 (void) mkdir_parents_label(*temp_path, 0700);
575
576 j->disk_fd = open(*temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
577 if (j->disk_fd < 0)
578 return log_error_errno(errno, "Failed to create %s: %m", *temp_path);
579
580 return 0;
581}
582
9854730b 583static int raw_pull_job_on_open_disk_raw(PullJob *j) {
dc2c282b 584 RawPull *i;
0d6e763b 585 int r;
90199220 586
0d6e763b
LP
587 assert(j);
588 assert(j->userdata);
90199220 589
0d6e763b 590 i = j->userdata;
8b71fce8 591 assert(i->raw_job == j);
90199220 592
91359193 593 r = raw_pull_job_on_open_disk_generic(i, j, "raw", &i->temp_path);
b6e676ce 594 if (r < 0)
91359193 595 return r;
1e20b411 596
137c6c6b 597 (void) import_set_nocow_and_log(j->disk_fd, i->temp_path);
90199220
LP
598 return 0;
599}
600
91359193 601static int raw_pull_job_on_open_disk_roothash(PullJob *j) {
9854730b 602 RawPull *i;
9854730b
LP
603
604 assert(j);
605 assert(j->userdata);
606
607 i = j->userdata;
91359193 608 assert(i->roothash_job == j);
9854730b 609
91359193
LP
610 return raw_pull_job_on_open_disk_generic(i, j, "roothash", &i->roothash_temp_path);
611}
9854730b 612
91359193
LP
613static int raw_pull_job_on_open_disk_settings(PullJob *j) {
614 RawPull *i;
9854730b 615
91359193
LP
616 assert(j);
617 assert(j->userdata);
9854730b 618
91359193
LP
619 i = j->userdata;
620 assert(i->settings_job == j);
9854730b 621
91359193 622 return raw_pull_job_on_open_disk_generic(i, j, "settings", &i->settings_temp_path);
9854730b
LP
623}
624
dc2c282b
LP
625static void raw_pull_job_on_progress(PullJob *j) {
626 RawPull *i;
7079cfef
LP
627
628 assert(j);
629 assert(j->userdata);
630
631 i = j->userdata;
632
dc2c282b 633 raw_pull_report_progress(i, RAW_DOWNLOADING);
7079cfef
LP
634}
635
9854730b
LP
636int raw_pull_start(
637 RawPull *i,
638 const char *url,
639 const char *local,
640 bool force_local,
641 ImportVerify verify,
91359193
LP
642 bool settings,
643 bool roothash) {
9854730b 644
90199220
LP
645 int r;
646
0d6e763b 647 assert(i);
8f695058
LP
648 assert(verify < _IMPORT_VERIFY_MAX);
649 assert(verify >= 0);
90199220 650
0d6e763b
LP
651 if (!http_url_is_valid(url))
652 return -EINVAL;
90199220 653
0d6e763b
LP
654 if (local && !machine_name_is_valid(local))
655 return -EINVAL;
087682d1 656
8b71fce8
LP
657 if (i->raw_job)
658 return -EBUSY;
659
0d6e763b 660 r = free_and_strdup(&i->local, local);
90199220
LP
661 if (r < 0)
662 return r;
9854730b 663
0d6e763b 664 i->force_local = force_local;
8f695058 665 i->verify = verify;
9854730b 666 i->settings = settings;
91359193 667 i->roothash = roothash;
90199220 668
85dbc41d 669 /* Queue job for the image itself */
dc2c282b 670 r = pull_job_new(&i->raw_job, url, i->glue, i);
90199220
LP
671 if (r < 0)
672 return r;
673
dc2c282b 674 i->raw_job->on_finished = raw_pull_job_on_finished;
9854730b 675 i->raw_job->on_open_disk = raw_pull_job_on_open_disk_raw;
dc2c282b 676 i->raw_job->on_progress = raw_pull_job_on_progress;
98c38001 677 i->raw_job->calc_checksum = verify != IMPORT_VERIFY_NO;
90199220 678
dc2c282b 679 r = pull_find_old_etags(url, i->image_root, DT_REG, ".raw-", ".raw", &i->raw_job->old_etags);
90199220
LP
680 if (r < 0)
681 return r;
682
91359193
LP
683 if (roothash) {
684 r = pull_make_auxiliary_job(&i->roothash_job, url, raw_strip_suffixes, ".roothash", i->glue, raw_pull_job_on_finished, i);
685 if (r < 0)
686 return r;
687
688 i->roothash_job->on_open_disk = raw_pull_job_on_open_disk_roothash;
689 i->roothash_job->on_progress = raw_pull_job_on_progress;
690 i->roothash_job->calc_checksum = verify != IMPORT_VERIFY_NO;
691 }
692
9854730b 693 if (settings) {
91359193 694 r = pull_make_auxiliary_job(&i->settings_job, url, raw_strip_suffixes, ".nspawn", i->glue, raw_pull_job_on_finished, i);
9854730b
LP
695 if (r < 0)
696 return r;
697
698 i->settings_job->on_open_disk = raw_pull_job_on_open_disk_settings;
699 i->settings_job->on_progress = raw_pull_job_on_progress;
700 i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO;
9854730b
LP
701 }
702
dc2c282b 703 r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, raw_pull_job_on_finished, i);
98c38001
LP
704 if (r < 0)
705 return r;
85dbc41d 706
dc2c282b 707 r = pull_job_begin(i->raw_job);
85dbc41d
LP
708 if (r < 0)
709 return r;
710
91359193
LP
711 if (i->roothash_job) {
712 r = pull_job_begin(i->roothash_job);
713 if (r < 0)
714 return r;
715 }
716
9854730b
LP
717 if (i->settings_job) {
718 r = pull_job_begin(i->settings_job);
719 if (r < 0)
720 return r;
721 }
722
98c38001 723 if (i->checksum_job) {
dc2c282b 724 i->checksum_job->on_progress = raw_pull_job_on_progress;
697be0be 725 i->checksum_job->style = VERIFICATION_PER_FILE;
7079cfef 726
dc2c282b 727 r = pull_job_begin(i->checksum_job);
3576d631
LP
728 if (r < 0)
729 return r;
730 }
731
732 if (i->signature_job) {
dc2c282b 733 i->signature_job->on_progress = raw_pull_job_on_progress;
7079cfef 734
dc2c282b 735 r = pull_job_begin(i->signature_job);
3576d631
LP
736 if (r < 0)
737 return r;
738 }
739
85dbc41d 740 return 0;
90199220 741}