LCOV - code coverage report
Current view: top level - import - pull-raw.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 405 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 16 0.0 %

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

Generated by: LCOV version 1.14