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