]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/import/pull-raw.c
tree-wide: remove unused variables
[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.");
697be0be 481 } else if (j->error != 0 && j != i->signature_job) {
98c38001 482 if (j == i->checksum_job)
3576d631 483 log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
3576d631
LP
484 else
485 log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)");
486
0d6e763b
LP
487 r = j->error;
488 goto finish;
8620a9a3
LP
489 }
490
0d6e763b
LP
491 /* This is invoked if either the download completed
492 * successfully, or the download was skipped because we
85dbc41d 493 * already have the etag. In this case ->etag_exists is
3576d631
LP
494 * true.
495 *
496 * We only do something when we got all three files */
85dbc41d 497
dc2c282b 498 if (!raw_pull_is_done(i))
3576d631 499 return;
8620a9a3 500
697be0be
TB
501 if (i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) {
502 log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
503
504 r = i->signature_job->error;
505 goto finish;
506 }
507
91359193
LP
508 if (i->roothash_job)
509 i->roothash_job->disk_fd = safe_close(i->roothash_job->disk_fd);
9854730b
LP
510 if (i->settings_job)
511 i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd);
512
91359193
LP
513 r = raw_pull_determine_path(i, ".raw", &i->final_path);
514 if (r < 0)
515 goto finish;
516
3576d631 517 if (!i->raw_job->etag_exists) {
98c38001 518 /* This is a new download, verify it, and move it into place */
3576d631
LP
519 assert(i->raw_job->disk_fd >= 0);
520
dc2c282b 521 raw_pull_report_progress(i, RAW_VERIFYING);
7079cfef 522
91359193 523 r = pull_verify(i->raw_job, i->roothash_job, i->settings_job, i->checksum_job, i->signature_job);
0d6e763b
LP
524 if (r < 0)
525 goto finish;
8620a9a3 526
dc2c282b 527 raw_pull_report_progress(i, RAW_UNPACKING);
7079cfef 528
dc2c282b 529 r = raw_pull_maybe_convert_qcow2(i);
0d6e763b
LP
530 if (r < 0)
531 goto finish;
85dbc41d 532
dc2c282b 533 raw_pull_report_progress(i, RAW_FINALIZING);
7079cfef 534
b6e676ce 535 r = import_make_read_only_fd(i->raw_job->disk_fd);
3576d631
LP
536 if (r < 0)
537 goto finish;
85dbc41d 538
f85ef957 539 r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
3576d631 540 if (r < 0) {
f85ef957 541 log_error_errno(r, "Failed to move RAW file into place: %m");
3576d631
LP
542 goto finish;
543 }
8f695058 544
9854730b
LP
545 i->temp_path = mfree(i->temp_path);
546
91359193
LP
547 if (i->roothash_job &&
548 i->roothash_job->error == 0) {
549 r = raw_pull_rename_auxiliary_file(i, ".roothash", &i->roothash_temp_path, &i->roothash_path);
9854730b
LP
550 if (r < 0)
551 goto finish;
91359193 552 }
9854730b 553
91359193
LP
554 if (i->settings_job &&
555 i->settings_job->error == 0) {
556 r = raw_pull_rename_auxiliary_file(i, ".nspawn", &i->settings_temp_path, &i->settings_path);
557 if (r < 0)
9854730b 558 goto finish;
9854730b 559 }
8620a9a3
LP
560 }
561
dc2c282b 562 raw_pull_report_progress(i, RAW_COPYING);
7079cfef 563
dc2c282b 564 r = raw_pull_make_local_copy(i);
8620a9a3 565 if (r < 0)
0d6e763b 566 goto finish;
90199220 567
0d6e763b 568 r = 0;
3576d631 569
0d6e763b 570finish:
3576d631
LP
571 if (i->on_finished)
572 i->on_finished(i, r, i->userdata);
573 else
574 sd_event_exit(i->event, r);
0d6e763b 575}
90199220 576
91359193
LP
577static int raw_pull_job_on_open_disk_generic(
578 RawPull *i,
579 PullJob *j,
580 const char *extra,
581 char **temp_path) {
582
91359193
LP
583 int r;
584
585 assert(i);
586 assert(j);
587 assert(extra);
588 assert(temp_path);
589
590 if (!*temp_path) {
591 r = tempfn_random_child(i->image_root, extra, temp_path);
592 if (r < 0)
593 return log_oom();
594 }
595
596 (void) mkdir_parents_label(*temp_path, 0700);
597
598 j->disk_fd = open(*temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
599 if (j->disk_fd < 0)
600 return log_error_errno(errno, "Failed to create %s: %m", *temp_path);
601
602 return 0;
603}
604
9854730b 605static int raw_pull_job_on_open_disk_raw(PullJob *j) {
dc2c282b 606 RawPull *i;
0d6e763b 607 int r;
90199220 608
0d6e763b
LP
609 assert(j);
610 assert(j->userdata);
90199220 611
0d6e763b 612 i = j->userdata;
8b71fce8 613 assert(i->raw_job == j);
90199220 614
91359193 615 r = raw_pull_job_on_open_disk_generic(i, j, "raw", &i->temp_path);
b6e676ce 616 if (r < 0)
91359193 617 return r;
1e20b411 618
1ed8f8c1 619 r = chattr_fd(j->disk_fd, FS_NOCOW_FL, FS_NOCOW_FL);
90199220 620 if (r < 0)
91359193 621 log_warning_errno(r, "Failed to set file attributes on %s, ignoring: %m", i->temp_path);
90199220
LP
622
623 return 0;
624}
625
91359193 626static int raw_pull_job_on_open_disk_roothash(PullJob *j) {
9854730b 627 RawPull *i;
9854730b
LP
628
629 assert(j);
630 assert(j->userdata);
631
632 i = j->userdata;
91359193 633 assert(i->roothash_job == j);
9854730b 634
91359193
LP
635 return raw_pull_job_on_open_disk_generic(i, j, "roothash", &i->roothash_temp_path);
636}
9854730b 637
91359193
LP
638static int raw_pull_job_on_open_disk_settings(PullJob *j) {
639 RawPull *i;
9854730b 640
91359193
LP
641 assert(j);
642 assert(j->userdata);
9854730b 643
91359193
LP
644 i = j->userdata;
645 assert(i->settings_job == j);
9854730b 646
91359193 647 return raw_pull_job_on_open_disk_generic(i, j, "settings", &i->settings_temp_path);
9854730b
LP
648}
649
dc2c282b
LP
650static void raw_pull_job_on_progress(PullJob *j) {
651 RawPull *i;
7079cfef
LP
652
653 assert(j);
654 assert(j->userdata);
655
656 i = j->userdata;
657
dc2c282b 658 raw_pull_report_progress(i, RAW_DOWNLOADING);
7079cfef
LP
659}
660
9854730b
LP
661int raw_pull_start(
662 RawPull *i,
663 const char *url,
664 const char *local,
665 bool force_local,
666 ImportVerify verify,
91359193
LP
667 bool settings,
668 bool roothash) {
9854730b 669
90199220
LP
670 int r;
671
0d6e763b 672 assert(i);
8f695058
LP
673 assert(verify < _IMPORT_VERIFY_MAX);
674 assert(verify >= 0);
90199220 675
0d6e763b
LP
676 if (!http_url_is_valid(url))
677 return -EINVAL;
90199220 678
0d6e763b
LP
679 if (local && !machine_name_is_valid(local))
680 return -EINVAL;
087682d1 681
8b71fce8
LP
682 if (i->raw_job)
683 return -EBUSY;
684
0d6e763b 685 r = free_and_strdup(&i->local, local);
90199220
LP
686 if (r < 0)
687 return r;
9854730b 688
0d6e763b 689 i->force_local = force_local;
8f695058 690 i->verify = verify;
9854730b 691 i->settings = settings;
91359193 692 i->roothash = roothash;
90199220 693
85dbc41d 694 /* Queue job for the image itself */
dc2c282b 695 r = pull_job_new(&i->raw_job, url, i->glue, i);
90199220
LP
696 if (r < 0)
697 return r;
698
dc2c282b 699 i->raw_job->on_finished = raw_pull_job_on_finished;
9854730b 700 i->raw_job->on_open_disk = raw_pull_job_on_open_disk_raw;
dc2c282b 701 i->raw_job->on_progress = raw_pull_job_on_progress;
98c38001 702 i->raw_job->calc_checksum = verify != IMPORT_VERIFY_NO;
26166c88 703 i->raw_job->grow_machine_directory = i->grow_machine_directory;
90199220 704
dc2c282b 705 r = pull_find_old_etags(url, i->image_root, DT_REG, ".raw-", ".raw", &i->raw_job->old_etags);
90199220
LP
706 if (r < 0)
707 return r;
708
91359193
LP
709 if (roothash) {
710 r = pull_make_auxiliary_job(&i->roothash_job, url, raw_strip_suffixes, ".roothash", i->glue, raw_pull_job_on_finished, i);
711 if (r < 0)
712 return r;
713
714 i->roothash_job->on_open_disk = raw_pull_job_on_open_disk_roothash;
715 i->roothash_job->on_progress = raw_pull_job_on_progress;
716 i->roothash_job->calc_checksum = verify != IMPORT_VERIFY_NO;
717 }
718
9854730b 719 if (settings) {
91359193 720 r = pull_make_auxiliary_job(&i->settings_job, url, raw_strip_suffixes, ".nspawn", i->glue, raw_pull_job_on_finished, i);
9854730b
LP
721 if (r < 0)
722 return r;
723
724 i->settings_job->on_open_disk = raw_pull_job_on_open_disk_settings;
725 i->settings_job->on_progress = raw_pull_job_on_progress;
726 i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO;
9854730b
LP
727 }
728
dc2c282b 729 r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, raw_pull_job_on_finished, i);
98c38001
LP
730 if (r < 0)
731 return r;
85dbc41d 732
dc2c282b 733 r = pull_job_begin(i->raw_job);
85dbc41d
LP
734 if (r < 0)
735 return r;
736
91359193
LP
737 if (i->roothash_job) {
738 r = pull_job_begin(i->roothash_job);
739 if (r < 0)
740 return r;
741 }
742
9854730b
LP
743 if (i->settings_job) {
744 r = pull_job_begin(i->settings_job);
745 if (r < 0)
746 return r;
747 }
748
98c38001 749 if (i->checksum_job) {
dc2c282b 750 i->checksum_job->on_progress = raw_pull_job_on_progress;
697be0be 751 i->checksum_job->style = VERIFICATION_PER_FILE;
7079cfef 752
dc2c282b 753 r = pull_job_begin(i->checksum_job);
3576d631
LP
754 if (r < 0)
755 return r;
756 }
757
758 if (i->signature_job) {
dc2c282b 759 i->signature_job->on_progress = raw_pull_job_on_progress;
7079cfef 760
dc2c282b 761 r = pull_job_begin(i->signature_job);
3576d631
LP
762 if (r < 0)
763 return r;
764 }
765
85dbc41d 766 return 0;
90199220 767}