]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/import/pull-raw.c
Replace free and reassignment with free_and_replace
[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
0d6e763b
LP
169 *ret = i;
170 i = NULL;
8620a9a3 171
2f64ba0e
LP
172 return 0;
173}
174
dc2c282b 175static void raw_pull_report_progress(RawPull *i, RawProgress p) {
7079cfef
LP
176 unsigned percent;
177
178 assert(i);
179
180 switch (p) {
181
182 case RAW_DOWNLOADING: {
183 unsigned remain = 80;
184
185 percent = 0;
186
9854730b
LP
187 if (i->settings_job) {
188 percent += i->settings_job->progress_percent * 5 / 100;
189 remain -= 5;
190 }
191
91359193
LP
192 if (i->roothash_job) {
193 percent += i->roothash_job->progress_percent * 5 / 100;
194 remain -= 5;
195 }
196
7079cfef
LP
197 if (i->checksum_job) {
198 percent += i->checksum_job->progress_percent * 5 / 100;
199 remain -= 5;
200 }
201
202 if (i->signature_job) {
203 percent += i->signature_job->progress_percent * 5 / 100;
204 remain -= 5;
205 }
206
207 if (i->raw_job)
208 percent += i->raw_job->progress_percent * remain / 100;
209 break;
210 }
211
212 case RAW_VERIFYING:
213 percent = 80;
214 break;
215
216 case RAW_UNPACKING:
217 percent = 85;
218 break;
219
220 case RAW_FINALIZING:
221 percent = 90;
222 break;
223
224 case RAW_COPYING:
225 percent = 95;
226 break;
227
228 default:
229 assert_not_reached("Unknown progress state");
230 }
231
232 sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
233 log_debug("Combined progress %u%%", percent);
234}
235
dc2c282b 236static int raw_pull_maybe_convert_qcow2(RawPull *i) {
edce2aed
LP
237 _cleanup_close_ int converted_fd = -1;
238 _cleanup_free_ char *t = NULL;
239 int r;
240
0d6e763b
LP
241 assert(i);
242 assert(i->raw_job);
edce2aed 243
0d6e763b 244 r = qcow2_detect(i->raw_job->disk_fd);
edce2aed
LP
245 if (r < 0)
246 return log_error_errno(r, "Failed to detect whether this is a QCOW2 image: %m");
247 if (r == 0)
248 return 0;
249
250 /* This is a QCOW2 image, let's convert it */
14bcf25c 251 r = tempfn_random(i->final_path, NULL, &t);
edce2aed
LP
252 if (r < 0)
253 return log_oom();
254
b6e676ce 255 converted_fd = open(t, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
edce2aed
LP
256 if (converted_fd < 0)
257 return log_error_errno(errno, "Failed to create %s: %m", t);
258
1ed8f8c1 259 r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL);
0d6e763b 260 if (r < 0)
709f6e46 261 log_warning_errno(r, "Failed to set file attributes on %s: %m", t);
0d6e763b 262
ec5cb56e
LP
263 log_info("Unpacking QCOW2 file.");
264
0d6e763b 265 r = qcow2_convert(i->raw_job->disk_fd, converted_fd);
edce2aed
LP
266 if (r < 0) {
267 unlink(t);
268 return log_error_errno(r, "Failed to convert qcow2 image: %m");
269 }
270
b6e676ce 271 (void) unlink(i->temp_path);
f9ecfd3b 272 free_and_replace(i->temp_path, t);
edce2aed 273
0d6e763b
LP
274 safe_close(i->raw_job->disk_fd);
275 i->raw_job->disk_fd = converted_fd;
edce2aed
LP
276 converted_fd = -1;
277
278 return 1;
279}
280
91359193
LP
281static int raw_pull_determine_path(RawPull *i, const char *suffix, char **field) {
282 int r;
283
284 assert(i);
285 assert(field);
286
287 if (*field)
288 return 0;
289
290 assert(i->raw_job);
291
292 r = pull_make_path(i->raw_job->url, i->raw_job->etag, i->image_root, ".raw-", suffix, field);
293 if (r < 0)
294 return log_oom();
295
296 return 1;
297}
298
299static int raw_pull_copy_auxiliary_file(
300 RawPull *i,
301 const char *suffix,
302 char **path) {
303
304 const char *local;
305 int r;
306
307 assert(i);
308 assert(suffix);
309 assert(path);
310
311 r = raw_pull_determine_path(i, suffix, path);
312 if (r < 0)
313 return r;
314
315 local = strjoina(i->image_root, "/", i->local, suffix);
316
1c876927 317 r = copy_file_atomic(*path, local, 0644, 0, COPY_REFLINK | (i->force_local ? COPY_REPLACE : 0));
91359193
LP
318 if (r == -EEXIST)
319 log_warning_errno(r, "File %s already exists, not replacing.", local);
320 else if (r == -ENOENT)
321 log_debug_errno(r, "Skipping creation of auxiliary file, since none was found.");
322 else if (r < 0)
323 log_warning_errno(r, "Failed to copy file %s, ignoring: %m", local);
324 else
325 log_info("Created new file %s.", local);
326
327 return 0;
328}
329
dc2c282b 330static int raw_pull_make_local_copy(RawPull *i) {
0d6e763b
LP
331 _cleanup_free_ char *tp = NULL;
332 _cleanup_close_ int dfd = -1;
333 const char *p;
90199220
LP
334 int r;
335
0d6e763b
LP
336 assert(i);
337 assert(i->raw_job);
90199220 338
0d6e763b 339 if (!i->local)
90199220
LP
340 return 0;
341
85dbc41d
LP
342 if (i->raw_job->etag_exists) {
343 /* We have downloaded this one previously, reopen it */
344
345 assert(i->raw_job->disk_fd < 0);
346
0d6e763b
LP
347 i->raw_job->disk_fd = open(i->final_path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
348 if (i->raw_job->disk_fd < 0)
349 return log_error_errno(errno, "Failed to open vendor image: %m");
85dbc41d
LP
350 } else {
351 /* We freshly downloaded the image, use it */
352
353 assert(i->raw_job->disk_fd >= 0);
354
355 if (lseek(i->raw_job->disk_fd, SEEK_SET, 0) == (off_t) -1)
356 return log_error_errno(errno, "Failed to seek to beginning of vendor image: %m");
90199220
LP
357 }
358
63c372cb 359 p = strjoina(i->image_root, "/", i->local, ".raw");
49bb233b 360
d9e2daaf
LP
361 if (i->force_local)
362 (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
49bb233b 363
14bcf25c 364 r = tempfn_random(p, NULL, &tp);
49bb233b 365 if (r < 0)
0d6e763b 366 return log_oom();
49bb233b 367
0d6e763b
LP
368 dfd = open(tp, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
369 if (dfd < 0)
370 return log_error_errno(errno, "Failed to create writable copy of image: %m");
49bb233b 371
0d6e763b
LP
372 /* Turn off COW writing. This should greatly improve
373 * performance on COW file systems like btrfs, since it
374 * reduces fragmentation caused by not allowing in-place
375 * writes. */
1ed8f8c1 376 r = chattr_fd(dfd, FS_NOCOW_FL, FS_NOCOW_FL);
0d6e763b 377 if (r < 0)
709f6e46 378 log_warning_errno(r, "Failed to set file attributes on %s: %m", tp);
90199220 379
1c876927 380 r = copy_bytes(i->raw_job->disk_fd, dfd, (uint64_t) -1, COPY_REFLINK);
90199220 381 if (r < 0) {
0d6e763b
LP
382 unlink(tp);
383 return log_error_errno(r, "Failed to make writable copy of image: %m");
90199220
LP
384 }
385
0d6e763b
LP
386 (void) copy_times(i->raw_job->disk_fd, dfd);
387 (void) copy_xattr(i->raw_job->disk_fd, dfd);
1e20b411 388
0d6e763b 389 dfd = safe_close(dfd);
1e20b411 390
0d6e763b
LP
391 r = rename(tp, p);
392 if (r < 0) {
5cfab271 393 r = log_error_errno(errno, "Failed to move writable image into place: %m");
0d6e763b 394 unlink(tp);
5cfab271 395 return r;
1e20b411
LP
396 }
397
0d6e763b 398 log_info("Created new local image '%s'.", i->local);
9854730b 399
91359193
LP
400 if (i->roothash) {
401 r = raw_pull_copy_auxiliary_file(i, ".roothash", &i->roothash_path);
402 if (r < 0)
403 return r;
404 }
9854730b 405
91359193
LP
406 if (i->settings) {
407 r = raw_pull_copy_auxiliary_file(i, ".nspawn", &i->settings_path);
408 if (r < 0)
409 return r;
9854730b
LP
410 }
411
1e20b411
LP
412 return 0;
413}
414
dc2c282b 415static bool raw_pull_is_done(RawPull *i) {
8b71fce8
LP
416 assert(i);
417 assert(i->raw_job);
418
9854730b 419 if (!PULL_JOB_IS_COMPLETE(i->raw_job))
8b71fce8 420 return false;
91359193
LP
421 if (i->roothash_job && !PULL_JOB_IS_COMPLETE(i->roothash_job))
422 return false;
9854730b 423 if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job))
8b71fce8 424 return false;
9854730b
LP
425 if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job))
426 return false;
427 if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job))
8b71fce8
LP
428 return false;
429
430 return true;
431}
432
91359193
LP
433static int raw_pull_rename_auxiliary_file(
434 RawPull *i,
435 const char *suffix,
436 char **temp_path,
437 char **path) {
438
439 int r;
440
441 assert(i);
442 assert(temp_path);
443 assert(suffix);
444 assert(path);
445
e0061812 446 /* Regenerate final name for this auxiliary file, we might know the etag of the file now, and we should
91359193
LP
447 * incorporate it in the file name if we can */
448 *path = mfree(*path);
449 r = raw_pull_determine_path(i, suffix, path);
450 if (r < 0)
451 return r;
452
453 r = import_make_read_only(*temp_path);
454 if (r < 0)
455 return r;
456
457 r = rename_noreplace(AT_FDCWD, *temp_path, AT_FDCWD, *path);
458 if (r < 0)
459 return log_error_errno(r, "Failed to rename file %s to %s: %m", *temp_path, *path);
460
461 *temp_path = mfree(*temp_path);
462
463 return 1;
464}
465
dc2c282b
LP
466static void raw_pull_job_on_finished(PullJob *j) {
467 RawPull *i;
8620a9a3
LP
468 int r;
469
0d6e763b
LP
470 assert(j);
471 assert(j->userdata);
8620a9a3 472
0d6e763b 473 i = j->userdata;
91359193
LP
474 if (j == i->roothash_job) {
475 if (j->error != 0)
476 log_info_errno(j->error, "Root hash file could not be retrieved, proceeding without.");
477 } else if (j == i->settings_job) {
9854730b
LP
478 if (j->error != 0)
479 log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
697be0be 480 } else if (j->error != 0 && j != i->signature_job) {
98c38001 481 if (j == i->checksum_job)
3576d631 482 log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
3576d631
LP
483 else
484 log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)");
485
0d6e763b
LP
486 r = j->error;
487 goto finish;
8620a9a3
LP
488 }
489
0d6e763b
LP
490 /* This is invoked if either the download completed
491 * successfully, or the download was skipped because we
85dbc41d 492 * already have the etag. In this case ->etag_exists is
3576d631
LP
493 * true.
494 *
495 * We only do something when we got all three files */
85dbc41d 496
dc2c282b 497 if (!raw_pull_is_done(i))
3576d631 498 return;
8620a9a3 499
c9fb8c7c 500 if (i->signature_job && i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) {
697be0be
TB
501 log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
502
503 r = i->signature_job->error;
504 goto finish;
505 }
506
91359193
LP
507 if (i->roothash_job)
508 i->roothash_job->disk_fd = safe_close(i->roothash_job->disk_fd);
9854730b
LP
509 if (i->settings_job)
510 i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd);
511
91359193
LP
512 r = raw_pull_determine_path(i, ".raw", &i->final_path);
513 if (r < 0)
514 goto finish;
515
3576d631 516 if (!i->raw_job->etag_exists) {
98c38001 517 /* This is a new download, verify it, and move it into place */
3576d631
LP
518 assert(i->raw_job->disk_fd >= 0);
519
dc2c282b 520 raw_pull_report_progress(i, RAW_VERIFYING);
7079cfef 521
91359193 522 r = pull_verify(i->raw_job, i->roothash_job, i->settings_job, i->checksum_job, i->signature_job);
0d6e763b
LP
523 if (r < 0)
524 goto finish;
8620a9a3 525
dc2c282b 526 raw_pull_report_progress(i, RAW_UNPACKING);
7079cfef 527
dc2c282b 528 r = raw_pull_maybe_convert_qcow2(i);
0d6e763b
LP
529 if (r < 0)
530 goto finish;
85dbc41d 531
dc2c282b 532 raw_pull_report_progress(i, RAW_FINALIZING);
7079cfef 533
b6e676ce 534 r = import_make_read_only_fd(i->raw_job->disk_fd);
3576d631
LP
535 if (r < 0)
536 goto finish;
85dbc41d 537
f85ef957 538 r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
3576d631 539 if (r < 0) {
dc38f65a 540 log_error_errno(r, "Failed to rename raw file to %s: %m", i->final_path);
3576d631
LP
541 goto finish;
542 }
8f695058 543
9854730b
LP
544 i->temp_path = mfree(i->temp_path);
545
91359193
LP
546 if (i->roothash_job &&
547 i->roothash_job->error == 0) {
548 r = raw_pull_rename_auxiliary_file(i, ".roothash", &i->roothash_temp_path, &i->roothash_path);
9854730b
LP
549 if (r < 0)
550 goto finish;
91359193 551 }
9854730b 552
91359193
LP
553 if (i->settings_job &&
554 i->settings_job->error == 0) {
555 r = raw_pull_rename_auxiliary_file(i, ".nspawn", &i->settings_temp_path, &i->settings_path);
556 if (r < 0)
9854730b 557 goto finish;
9854730b 558 }
8620a9a3
LP
559 }
560
dc2c282b 561 raw_pull_report_progress(i, RAW_COPYING);
7079cfef 562
dc2c282b 563 r = raw_pull_make_local_copy(i);
8620a9a3 564 if (r < 0)
0d6e763b 565 goto finish;
90199220 566
0d6e763b 567 r = 0;
3576d631 568
0d6e763b 569finish:
3576d631
LP
570 if (i->on_finished)
571 i->on_finished(i, r, i->userdata);
572 else
573 sd_event_exit(i->event, r);
0d6e763b 574}
90199220 575
91359193
LP
576static int raw_pull_job_on_open_disk_generic(
577 RawPull *i,
578 PullJob *j,
579 const char *extra,
580 char **temp_path) {
581
91359193
LP
582 int r;
583
584 assert(i);
585 assert(j);
586 assert(extra);
587 assert(temp_path);
588
589 if (!*temp_path) {
590 r = tempfn_random_child(i->image_root, extra, temp_path);
591 if (r < 0)
592 return log_oom();
593 }
594
595 (void) mkdir_parents_label(*temp_path, 0700);
596
597 j->disk_fd = open(*temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
598 if (j->disk_fd < 0)
599 return log_error_errno(errno, "Failed to create %s: %m", *temp_path);
600
601 return 0;
602}
603
9854730b 604static int raw_pull_job_on_open_disk_raw(PullJob *j) {
dc2c282b 605 RawPull *i;
0d6e763b 606 int r;
90199220 607
0d6e763b
LP
608 assert(j);
609 assert(j->userdata);
90199220 610
0d6e763b 611 i = j->userdata;
8b71fce8 612 assert(i->raw_job == j);
90199220 613
91359193 614 r = raw_pull_job_on_open_disk_generic(i, j, "raw", &i->temp_path);
b6e676ce 615 if (r < 0)
91359193 616 return r;
1e20b411 617
1ed8f8c1 618 r = chattr_fd(j->disk_fd, FS_NOCOW_FL, FS_NOCOW_FL);
90199220 619 if (r < 0)
91359193 620 log_warning_errno(r, "Failed to set file attributes on %s, ignoring: %m", i->temp_path);
90199220
LP
621
622 return 0;
623}
624
91359193 625static int raw_pull_job_on_open_disk_roothash(PullJob *j) {
9854730b 626 RawPull *i;
9854730b
LP
627
628 assert(j);
629 assert(j->userdata);
630
631 i = j->userdata;
91359193 632 assert(i->roothash_job == j);
9854730b 633
91359193
LP
634 return raw_pull_job_on_open_disk_generic(i, j, "roothash", &i->roothash_temp_path);
635}
9854730b 636
91359193
LP
637static int raw_pull_job_on_open_disk_settings(PullJob *j) {
638 RawPull *i;
9854730b 639
91359193
LP
640 assert(j);
641 assert(j->userdata);
9854730b 642
91359193
LP
643 i = j->userdata;
644 assert(i->settings_job == j);
9854730b 645
91359193 646 return raw_pull_job_on_open_disk_generic(i, j, "settings", &i->settings_temp_path);
9854730b
LP
647}
648
dc2c282b
LP
649static void raw_pull_job_on_progress(PullJob *j) {
650 RawPull *i;
7079cfef
LP
651
652 assert(j);
653 assert(j->userdata);
654
655 i = j->userdata;
656
dc2c282b 657 raw_pull_report_progress(i, RAW_DOWNLOADING);
7079cfef
LP
658}
659
9854730b
LP
660int raw_pull_start(
661 RawPull *i,
662 const char *url,
663 const char *local,
664 bool force_local,
665 ImportVerify verify,
91359193
LP
666 bool settings,
667 bool roothash) {
9854730b 668
90199220
LP
669 int r;
670
0d6e763b 671 assert(i);
8f695058
LP
672 assert(verify < _IMPORT_VERIFY_MAX);
673 assert(verify >= 0);
90199220 674
0d6e763b
LP
675 if (!http_url_is_valid(url))
676 return -EINVAL;
90199220 677
0d6e763b
LP
678 if (local && !machine_name_is_valid(local))
679 return -EINVAL;
087682d1 680
8b71fce8
LP
681 if (i->raw_job)
682 return -EBUSY;
683
0d6e763b 684 r = free_and_strdup(&i->local, local);
90199220
LP
685 if (r < 0)
686 return r;
9854730b 687
0d6e763b 688 i->force_local = force_local;
8f695058 689 i->verify = verify;
9854730b 690 i->settings = settings;
91359193 691 i->roothash = roothash;
90199220 692
85dbc41d 693 /* Queue job for the image itself */
dc2c282b 694 r = pull_job_new(&i->raw_job, url, i->glue, i);
90199220
LP
695 if (r < 0)
696 return r;
697
dc2c282b 698 i->raw_job->on_finished = raw_pull_job_on_finished;
9854730b 699 i->raw_job->on_open_disk = raw_pull_job_on_open_disk_raw;
dc2c282b 700 i->raw_job->on_progress = raw_pull_job_on_progress;
98c38001 701 i->raw_job->calc_checksum = verify != IMPORT_VERIFY_NO;
26166c88 702 i->raw_job->grow_machine_directory = i->grow_machine_directory;
90199220 703
dc2c282b 704 r = pull_find_old_etags(url, i->image_root, DT_REG, ".raw-", ".raw", &i->raw_job->old_etags);
90199220
LP
705 if (r < 0)
706 return r;
707
91359193
LP
708 if (roothash) {
709 r = pull_make_auxiliary_job(&i->roothash_job, url, raw_strip_suffixes, ".roothash", i->glue, raw_pull_job_on_finished, i);
710 if (r < 0)
711 return r;
712
713 i->roothash_job->on_open_disk = raw_pull_job_on_open_disk_roothash;
714 i->roothash_job->on_progress = raw_pull_job_on_progress;
715 i->roothash_job->calc_checksum = verify != IMPORT_VERIFY_NO;
716 }
717
9854730b 718 if (settings) {
91359193 719 r = pull_make_auxiliary_job(&i->settings_job, url, raw_strip_suffixes, ".nspawn", i->glue, raw_pull_job_on_finished, i);
9854730b
LP
720 if (r < 0)
721 return r;
722
723 i->settings_job->on_open_disk = raw_pull_job_on_open_disk_settings;
724 i->settings_job->on_progress = raw_pull_job_on_progress;
725 i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO;
9854730b
LP
726 }
727
dc2c282b 728 r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, raw_pull_job_on_finished, i);
98c38001
LP
729 if (r < 0)
730 return r;
85dbc41d 731
dc2c282b 732 r = pull_job_begin(i->raw_job);
85dbc41d
LP
733 if (r < 0)
734 return r;
735
91359193
LP
736 if (i->roothash_job) {
737 r = pull_job_begin(i->roothash_job);
738 if (r < 0)
739 return r;
740 }
741
9854730b
LP
742 if (i->settings_job) {
743 r = pull_job_begin(i->settings_job);
744 if (r < 0)
745 return r;
746 }
747
98c38001 748 if (i->checksum_job) {
dc2c282b 749 i->checksum_job->on_progress = raw_pull_job_on_progress;
697be0be 750 i->checksum_job->style = VERIFICATION_PER_FILE;
7079cfef 751
dc2c282b 752 r = pull_job_begin(i->checksum_job);
3576d631
LP
753 if (r < 0)
754 return r;
755 }
756
757 if (i->signature_job) {
dc2c282b 758 i->signature_job->on_progress = raw_pull_job_on_progress;
7079cfef 759
dc2c282b 760 r = pull_job_begin(i->signature_job);
3576d631
LP
761 if (r < 0)
762 return r;
763 }
764
85dbc41d 765 return 0;
90199220 766}