LCOV - code coverage report
Current view: top level - import - pull.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 20 168 11.9 %
Date: 2019-08-22 15:41:25 Functions: 4 10 40.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <getopt.h>
       4             : #include <locale.h>
       5             : 
       6             : #include "sd-event.h"
       7             : #include "sd-id128.h"
       8             : 
       9             : #include "alloc-util.h"
      10             : #include "hostname-util.h"
      11             : #include "import-util.h"
      12             : #include "machine-image.h"
      13             : #include "main-func.h"
      14             : #include "parse-util.h"
      15             : #include "pull-raw.h"
      16             : #include "pull-tar.h"
      17             : #include "signal-util.h"
      18             : #include "string-util.h"
      19             : #include "verbs.h"
      20             : #include "web-util.h"
      21             : 
      22             : static bool arg_force = false;
      23             : static const char *arg_image_root = "/var/lib/machines";
      24             : static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
      25             : static bool arg_settings = true;
      26             : static bool arg_roothash = true;
      27             : 
      28           0 : static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
      29           0 :         log_notice("Transfer aborted.");
      30           0 :         sd_event_exit(sd_event_source_get_event(s), EINTR);
      31           0 :         return 0;
      32             : }
      33             : 
      34           0 : static void on_tar_finished(TarPull *pull, int error, void *userdata) {
      35           0 :         sd_event *event = userdata;
      36           0 :         assert(pull);
      37             : 
      38           0 :         if (error == 0)
      39           0 :                 log_info("Operation completed successfully.");
      40             : 
      41           0 :         sd_event_exit(event, abs(error));
      42           0 : }
      43             : 
      44           0 : static int pull_tar(int argc, char *argv[], void *userdata) {
      45           0 :         _cleanup_(tar_pull_unrefp) TarPull *pull = NULL;
      46           0 :         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
      47             :         const char *url, *local;
      48           0 :         _cleanup_free_ char *l = NULL, *ll = NULL;
      49             :         int r;
      50             : 
      51           0 :         url = argv[1];
      52           0 :         if (!http_url_is_valid(url)) {
      53           0 :                 log_error("URL '%s' is not valid.", url);
      54           0 :                 return -EINVAL;
      55             :         }
      56             : 
      57           0 :         if (argc >= 3)
      58           0 :                 local = argv[2];
      59             :         else {
      60           0 :                 r = import_url_last_component(url, &l);
      61           0 :                 if (r < 0)
      62           0 :                         return log_error_errno(r, "Failed get final component of URL: %m");
      63             : 
      64           0 :                 local = l;
      65             :         }
      66             : 
      67           0 :         local = empty_or_dash_to_null(local);
      68             : 
      69           0 :         if (local) {
      70           0 :                 r = tar_strip_suffixes(local, &ll);
      71           0 :                 if (r < 0)
      72           0 :                         return log_oom();
      73             : 
      74           0 :                 local = ll;
      75             : 
      76           0 :                 if (!machine_name_is_valid(local)) {
      77           0 :                         log_error("Local image name '%s' is not valid.", local);
      78           0 :                         return -EINVAL;
      79             :                 }
      80             : 
      81           0 :                 if (!arg_force) {
      82           0 :                         r = image_find(IMAGE_MACHINE, local, NULL);
      83           0 :                         if (r < 0) {
      84           0 :                                 if (r != -ENOENT)
      85           0 :                                         return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
      86             :                         } else {
      87           0 :                                 log_error("Image '%s' already exists.", local);
      88           0 :                                 return -EEXIST;
      89             :                         }
      90             :                 }
      91             : 
      92           0 :                 log_info("Pulling '%s', saving as '%s'.", url, local);
      93             :         } else
      94           0 :                 log_info("Pulling '%s'.", url);
      95             : 
      96           0 :         r = sd_event_default(&event);
      97           0 :         if (r < 0)
      98           0 :                 return log_error_errno(r, "Failed to allocate event loop: %m");
      99             : 
     100           0 :         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
     101           0 :         (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler,  NULL);
     102           0 :         (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
     103             : 
     104           0 :         r = tar_pull_new(&pull, event, arg_image_root, on_tar_finished, event);
     105           0 :         if (r < 0)
     106           0 :                 return log_error_errno(r, "Failed to allocate puller: %m");
     107             : 
     108           0 :         r = tar_pull_start(pull, url, local, arg_force, arg_verify, arg_settings);
     109           0 :         if (r < 0)
     110           0 :                 return log_error_errno(r, "Failed to pull image: %m");
     111             : 
     112           0 :         r = sd_event_loop(event);
     113           0 :         if (r < 0)
     114           0 :                 return log_error_errno(r, "Failed to run event loop: %m");
     115             : 
     116           0 :         log_info("Exiting.");
     117           0 :         return -r;
     118             : }
     119             : 
     120           0 : static void on_raw_finished(RawPull *pull, int error, void *userdata) {
     121           0 :         sd_event *event = userdata;
     122           0 :         assert(pull);
     123             : 
     124           0 :         if (error == 0)
     125           0 :                 log_info("Operation completed successfully.");
     126             : 
     127           0 :         sd_event_exit(event, abs(error));
     128           0 : }
     129             : 
     130           0 : static int pull_raw(int argc, char *argv[], void *userdata) {
     131           0 :         _cleanup_(raw_pull_unrefp) RawPull *pull = NULL;
     132           0 :         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
     133             :         const char *url, *local;
     134           0 :         _cleanup_free_ char *l = NULL, *ll = NULL;
     135             :         int r;
     136             : 
     137           0 :         url = argv[1];
     138           0 :         if (!http_url_is_valid(url)) {
     139           0 :                 log_error("URL '%s' is not valid.", url);
     140           0 :                 return -EINVAL;
     141             :         }
     142             : 
     143           0 :         if (argc >= 3)
     144           0 :                 local = argv[2];
     145             :         else {
     146           0 :                 r = import_url_last_component(url, &l);
     147           0 :                 if (r < 0)
     148           0 :                         return log_error_errno(r, "Failed get final component of URL: %m");
     149             : 
     150           0 :                 local = l;
     151             :         }
     152             : 
     153           0 :         local = empty_or_dash_to_null(local);
     154             : 
     155           0 :         if (local) {
     156           0 :                 r = raw_strip_suffixes(local, &ll);
     157           0 :                 if (r < 0)
     158           0 :                         return log_oom();
     159             : 
     160           0 :                 local = ll;
     161             : 
     162           0 :                 if (!machine_name_is_valid(local)) {
     163           0 :                         log_error("Local image name '%s' is not valid.", local);
     164           0 :                         return -EINVAL;
     165             :                 }
     166             : 
     167           0 :                 if (!arg_force) {
     168           0 :                         r = image_find(IMAGE_MACHINE, local, NULL);
     169           0 :                         if (r < 0) {
     170           0 :                                 if (r != -ENOENT)
     171           0 :                                         return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
     172             :                         } else {
     173           0 :                                 log_error("Image '%s' already exists.", local);
     174           0 :                                 return -EEXIST;
     175             :                         }
     176             :                 }
     177             : 
     178           0 :                 log_info("Pulling '%s', saving as '%s'.", url, local);
     179             :         } else
     180           0 :                 log_info("Pulling '%s'.", url);
     181             : 
     182           0 :         r = sd_event_default(&event);
     183           0 :         if (r < 0)
     184           0 :                 return log_error_errno(r, "Failed to allocate event loop: %m");
     185             : 
     186           0 :         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
     187           0 :         (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler,  NULL);
     188           0 :         (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
     189             : 
     190           0 :         r = raw_pull_new(&pull, event, arg_image_root, on_raw_finished, event);
     191           0 :         if (r < 0)
     192           0 :                 return log_error_errno(r, "Failed to allocate puller: %m");
     193             : 
     194           0 :         r = raw_pull_start(pull, url, local, arg_force, arg_verify, arg_settings, arg_roothash);
     195           0 :         if (r < 0)
     196           0 :                 return log_error_errno(r, "Failed to pull image: %m");
     197             : 
     198           0 :         r = sd_event_loop(event);
     199           0 :         if (r < 0)
     200           0 :                 return log_error_errno(r, "Failed to run event loop: %m");
     201             : 
     202           0 :         log_info("Exiting.");
     203           0 :         return -r;
     204             : }
     205             : 
     206           3 : static int help(int argc, char *argv[], void *userdata) {
     207             : 
     208           3 :         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
     209             :                "Download container or virtual machine images.\n\n"
     210             :                "  -h --help                   Show this help\n"
     211             :                "     --version                Show package version\n"
     212             :                "     --force                  Force creation of image\n"
     213             :                "     --verify=MODE            Verify downloaded image, one of: 'no',\n"
     214             :                "                              'checksum', 'signature'\n"
     215             :                "     --settings=BOOL          Download settings file with image\n"
     216             :                "     --roothash=BOOL          Download root hash file with image\n"
     217             :                "     --image-root=PATH        Image root directory\n\n"
     218             :                "Commands:\n"
     219             :                "  tar URL [NAME]              Download a TAR image\n"
     220             :                "  raw URL [NAME]              Download a RAW image\n",
     221             :                program_invocation_short_name);
     222             : 
     223           3 :         return 0;
     224             : }
     225             : 
     226           4 : static int parse_argv(int argc, char *argv[]) {
     227             : 
     228             :         enum {
     229             :                 ARG_VERSION = 0x100,
     230             :                 ARG_FORCE,
     231             :                 ARG_IMAGE_ROOT,
     232             :                 ARG_VERIFY,
     233             :                 ARG_SETTINGS,
     234             :                 ARG_ROOTHASH,
     235             :         };
     236             : 
     237             :         static const struct option options[] = {
     238             :                 { "help",            no_argument,       NULL, 'h'                 },
     239             :                 { "version",         no_argument,       NULL, ARG_VERSION         },
     240             :                 { "force",           no_argument,       NULL, ARG_FORCE           },
     241             :                 { "image-root",      required_argument, NULL, ARG_IMAGE_ROOT      },
     242             :                 { "verify",          required_argument, NULL, ARG_VERIFY          },
     243             :                 { "settings",        required_argument, NULL, ARG_SETTINGS        },
     244             :                 { "roothash",        required_argument, NULL, ARG_ROOTHASH        },
     245             :                 {}
     246             :         };
     247             : 
     248             :         int c, r;
     249             : 
     250           4 :         assert(argc >= 0);
     251           4 :         assert(argv);
     252             : 
     253           4 :         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
     254             : 
     255           4 :                 switch (c) {
     256             : 
     257           3 :                 case 'h':
     258           3 :                         return help(0, NULL, NULL);
     259             : 
     260           0 :                 case ARG_VERSION:
     261           0 :                         return version();
     262             : 
     263           0 :                 case ARG_FORCE:
     264           0 :                         arg_force = true;
     265           0 :                         break;
     266             : 
     267           0 :                 case ARG_IMAGE_ROOT:
     268           0 :                         arg_image_root = optarg;
     269           0 :                         break;
     270             : 
     271           0 :                 case ARG_VERIFY:
     272           0 :                         arg_verify = import_verify_from_string(optarg);
     273           0 :                         if (arg_verify < 0)
     274           0 :                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     275             :                                                        "Invalid verification setting '%s'", optarg);
     276             : 
     277           0 :                         break;
     278             : 
     279           0 :                 case ARG_SETTINGS:
     280           0 :                         r = parse_boolean(optarg);
     281           0 :                         if (r < 0)
     282           0 :                                 return log_error_errno(r, "Failed to parse --settings= parameter '%s': %m", optarg);
     283             : 
     284           0 :                         arg_settings = r;
     285           0 :                         break;
     286             : 
     287           0 :                 case ARG_ROOTHASH:
     288           0 :                         r = parse_boolean(optarg);
     289           0 :                         if (r < 0)
     290           0 :                                 return log_error_errno(r, "Failed to parse --roothash= parameter '%s': %m", optarg);
     291             : 
     292           0 :                         arg_roothash = r;
     293           0 :                         break;
     294             : 
     295           1 :                 case '?':
     296           1 :                         return -EINVAL;
     297             : 
     298           0 :                 default:
     299           0 :                         assert_not_reached("Unhandled option");
     300             :                 }
     301             : 
     302           0 :         return 1;
     303             : }
     304             : 
     305           0 : static int pull_main(int argc, char *argv[]) {
     306             :         static const Verb verbs[] = {
     307             :                 { "help", VERB_ANY, VERB_ANY, 0, help     },
     308             :                 { "tar",  2,        3,        0, pull_tar },
     309             :                 { "raw",  2,        3,        0, pull_raw },
     310             :                 {}
     311             :         };
     312             : 
     313           0 :         return dispatch_verb(argc, argv, verbs, NULL);
     314             : }
     315             : 
     316           4 : static int run(int argc, char *argv[]) {
     317             :         int r;
     318             : 
     319           4 :         setlocale(LC_ALL, "");
     320           4 :         log_parse_environment();
     321           4 :         log_open();
     322             : 
     323           4 :         r = parse_argv(argc, argv);
     324           4 :         if (r <= 0)
     325           4 :                 return r;
     326             : 
     327           0 :         (void) ignore_signals(SIGPIPE, -1);
     328             : 
     329           0 :         return pull_main(argc, argv);
     330             : }
     331             : 
     332           4 : DEFINE_MAIN_FUNCTION(run);

Generated by: LCOV version 1.14