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