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