LCOV - code coverage report
Current view: top level - import - import.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 20 170 11.8 %
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 "fd-util.h"
      11             : #include "fs-util.h"
      12             : #include "hostname-util.h"
      13             : #include "import-raw.h"
      14             : #include "import-tar.h"
      15             : #include "import-util.h"
      16             : #include "machine-image.h"
      17             : #include "main-func.h"
      18             : #include "signal-util.h"
      19             : #include "string-util.h"
      20             : #include "verbs.h"
      21             : 
      22             : static bool arg_force = false;
      23             : static bool arg_read_only = false;
      24             : static const char *arg_image_root = "/var/lib/machines";
      25             : 
      26           0 : static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
      27           0 :         log_notice("Transfer aborted.");
      28           0 :         sd_event_exit(sd_event_source_get_event(s), EINTR);
      29           0 :         return 0;
      30             : }
      31             : 
      32           0 : static void on_tar_finished(TarImport *import, int error, void *userdata) {
      33           0 :         sd_event *event = userdata;
      34           0 :         assert(import);
      35             : 
      36           0 :         if (error == 0)
      37           0 :                 log_info("Operation completed successfully.");
      38             : 
      39           0 :         sd_event_exit(event, abs(error));
      40           0 : }
      41             : 
      42           0 : static int import_tar(int argc, char *argv[], void *userdata) {
      43           0 :         _cleanup_(tar_import_unrefp) TarImport *import = NULL;
      44           0 :         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
      45           0 :         const char *path = NULL, *local = NULL;
      46           0 :         _cleanup_free_ char *ll = NULL;
      47           0 :         _cleanup_close_ int open_fd = -1;
      48             :         int r, fd;
      49             : 
      50           0 :         if (argc >= 2)
      51           0 :                 path = argv[1];
      52           0 :         path = empty_or_dash_to_null(path);
      53             : 
      54           0 :         if (argc >= 3)
      55           0 :                 local = argv[2];
      56           0 :         else if (path)
      57           0 :                 local = basename(path);
      58           0 :         local = empty_or_dash_to_null(local);
      59             : 
      60           0 :         if (local) {
      61           0 :                 r = tar_strip_suffixes(local, &ll);
      62           0 :                 if (r < 0)
      63           0 :                         return log_oom();
      64             : 
      65           0 :                 local = ll;
      66             : 
      67           0 :                 if (!machine_name_is_valid(local)) {
      68           0 :                         log_error("Local image name '%s' is not valid.", local);
      69           0 :                         return -EINVAL;
      70             :                 }
      71             : 
      72           0 :                 if (!arg_force) {
      73           0 :                         r = image_find(IMAGE_MACHINE, local, NULL);
      74           0 :                         if (r < 0) {
      75           0 :                                 if (r != -ENOENT)
      76           0 :                                         return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
      77             :                         } else {
      78           0 :                                 log_error("Image '%s' already exists.", local);
      79           0 :                                 return -EEXIST;
      80             :                         }
      81             :                 }
      82             :         } else
      83           0 :                 local = "imported";
      84             : 
      85           0 :         if (path) {
      86           0 :                 open_fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
      87           0 :                 if (open_fd < 0)
      88           0 :                         return log_error_errno(errno, "Failed to open tar image to import: %m");
      89             : 
      90           0 :                 fd = open_fd;
      91             : 
      92           0 :                 log_info("Importing '%s', saving as '%s'.", path, local);
      93             :         } else {
      94           0 :                 _cleanup_free_ char *pretty = NULL;
      95             : 
      96           0 :                 fd = STDIN_FILENO;
      97             : 
      98           0 :                 (void) fd_get_path(fd, &pretty);
      99           0 :                 log_info("Importing '%s', saving as '%s'.", strna(pretty), local);
     100             :         }
     101             : 
     102           0 :         r = sd_event_default(&event);
     103           0 :         if (r < 0)
     104           0 :                 return log_error_errno(r, "Failed to allocate event loop: %m");
     105             : 
     106           0 :         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
     107           0 :         (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler,  NULL);
     108           0 :         (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
     109             : 
     110           0 :         r = tar_import_new(&import, event, arg_image_root, on_tar_finished, event);
     111           0 :         if (r < 0)
     112           0 :                 return log_error_errno(r, "Failed to allocate importer: %m");
     113             : 
     114           0 :         r = tar_import_start(import, fd, local, arg_force, arg_read_only);
     115           0 :         if (r < 0)
     116           0 :                 return log_error_errno(r, "Failed to import image: %m");
     117             : 
     118           0 :         r = sd_event_loop(event);
     119           0 :         if (r < 0)
     120           0 :                 return log_error_errno(r, "Failed to run event loop: %m");
     121             : 
     122           0 :         log_info("Exiting.");
     123           0 :         return -r;
     124             : }
     125             : 
     126           0 : static void on_raw_finished(RawImport *import, int error, void *userdata) {
     127           0 :         sd_event *event = userdata;
     128           0 :         assert(import);
     129             : 
     130           0 :         if (error == 0)
     131           0 :                 log_info("Operation completed successfully.");
     132             : 
     133           0 :         sd_event_exit(event, abs(error));
     134           0 : }
     135             : 
     136           0 : static int import_raw(int argc, char *argv[], void *userdata) {
     137           0 :         _cleanup_(raw_import_unrefp) RawImport *import = NULL;
     138           0 :         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
     139           0 :         const char *path = NULL, *local = NULL;
     140           0 :         _cleanup_free_ char *ll = NULL;
     141           0 :         _cleanup_close_ int open_fd = -1;
     142             :         int r, fd;
     143             : 
     144           0 :         if (argc >= 2)
     145           0 :                 path = argv[1];
     146           0 :         path = empty_or_dash_to_null(path);
     147             : 
     148           0 :         if (argc >= 3)
     149           0 :                 local = argv[2];
     150           0 :         else if (path)
     151           0 :                 local = basename(path);
     152           0 :         local = empty_or_dash_to_null(local);
     153             : 
     154           0 :         if (local) {
     155           0 :                 r = raw_strip_suffixes(local, &ll);
     156           0 :                 if (r < 0)
     157           0 :                         return log_oom();
     158             : 
     159           0 :                 local = ll;
     160             : 
     161           0 :                 if (!machine_name_is_valid(local)) {
     162           0 :                         log_error("Local image name '%s' is not valid.", local);
     163           0 :                         return -EINVAL;
     164             :                 }
     165             : 
     166           0 :                 if (!arg_force) {
     167           0 :                         r = image_find(IMAGE_MACHINE, local, NULL);
     168           0 :                         if (r < 0) {
     169           0 :                                 if (r != -ENOENT)
     170           0 :                                         return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
     171             :                         } else {
     172           0 :                                 log_error("Image '%s' already exists.", local);
     173           0 :                                 return -EEXIST;
     174             :                         }
     175             :                 }
     176             :         } else
     177           0 :                 local = "imported";
     178             : 
     179           0 :         if (path) {
     180           0 :                 open_fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
     181           0 :                 if (open_fd < 0)
     182           0 :                         return log_error_errno(errno, "Failed to open raw image to import: %m");
     183             : 
     184           0 :                 fd = open_fd;
     185             : 
     186           0 :                 log_info("Importing '%s', saving as '%s'.", path, local);
     187             :         } else {
     188           0 :                 _cleanup_free_ char *pretty = NULL;
     189             : 
     190           0 :                 fd = STDIN_FILENO;
     191             : 
     192           0 :                 (void) fd_get_path(fd, &pretty);
     193           0 :                 log_info("Importing '%s', saving as '%s'.", strempty(pretty), local);
     194             :         }
     195             : 
     196           0 :         r = sd_event_default(&event);
     197           0 :         if (r < 0)
     198           0 :                 return log_error_errno(r, "Failed to allocate event loop: %m");
     199             : 
     200           0 :         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
     201           0 :         (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler,  NULL);
     202           0 :         (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
     203             : 
     204           0 :         r = raw_import_new(&import, event, arg_image_root, on_raw_finished, event);
     205           0 :         if (r < 0)
     206           0 :                 return log_error_errno(r, "Failed to allocate importer: %m");
     207             : 
     208           0 :         r = raw_import_start(import, fd, local, arg_force, arg_read_only);
     209           0 :         if (r < 0)
     210           0 :                 return log_error_errno(r, "Failed to import image: %m");
     211             : 
     212           0 :         r = sd_event_loop(event);
     213           0 :         if (r < 0)
     214           0 :                 return log_error_errno(r, "Failed to run event loop: %m");
     215             : 
     216           0 :         log_info("Exiting.");
     217           0 :         return -r;
     218             : }
     219             : 
     220           3 : static int help(int argc, char *argv[], void *userdata) {
     221             : 
     222           3 :         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
     223             :                "Import container or virtual machine images.\n\n"
     224             :                "  -h --help                   Show this help\n"
     225             :                "     --version                Show package version\n"
     226             :                "     --force                  Force creation of image\n"
     227             :                "     --image-root=PATH        Image root directory\n"
     228             :                "     --read-only              Create a read-only image\n\n"
     229             :                "Commands:\n"
     230             :                "  tar FILE [NAME]             Import a TAR image\n"
     231             :                "  raw FILE [NAME]             Import a RAW image\n",
     232             :                program_invocation_short_name);
     233             : 
     234           3 :         return 0;
     235             : }
     236             : 
     237           4 : static int parse_argv(int argc, char *argv[]) {
     238             : 
     239             :         enum {
     240             :                 ARG_VERSION = 0x100,
     241             :                 ARG_FORCE,
     242             :                 ARG_IMAGE_ROOT,
     243             :                 ARG_READ_ONLY,
     244             :         };
     245             : 
     246             :         static const struct option options[] = {
     247             :                 { "help",            no_argument,       NULL, 'h'                 },
     248             :                 { "version",         no_argument,       NULL, ARG_VERSION         },
     249             :                 { "force",           no_argument,       NULL, ARG_FORCE           },
     250             :                 { "image-root",      required_argument, NULL, ARG_IMAGE_ROOT      },
     251             :                 { "read-only",       no_argument,       NULL, ARG_READ_ONLY       },
     252             :                 {}
     253             :         };
     254             : 
     255             :         int c;
     256             : 
     257           4 :         assert(argc >= 0);
     258           4 :         assert(argv);
     259             : 
     260           4 :         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
     261             : 
     262           4 :                 switch (c) {
     263             : 
     264           3 :                 case 'h':
     265           3 :                         return help(0, NULL, NULL);
     266             : 
     267           0 :                 case ARG_VERSION:
     268           0 :                         return version();
     269             : 
     270           0 :                 case ARG_FORCE:
     271           0 :                         arg_force = true;
     272           0 :                         break;
     273             : 
     274           0 :                 case ARG_IMAGE_ROOT:
     275           0 :                         arg_image_root = optarg;
     276           0 :                         break;
     277             : 
     278           0 :                 case ARG_READ_ONLY:
     279           0 :                         arg_read_only = true;
     280           0 :                         break;
     281             : 
     282           1 :                 case '?':
     283           1 :                         return -EINVAL;
     284             : 
     285           0 :                 default:
     286           0 :                         assert_not_reached("Unhandled option");
     287             :                 }
     288             : 
     289           0 :         return 1;
     290             : }
     291             : 
     292           0 : static int import_main(int argc, char *argv[]) {
     293             :         static const Verb verbs[] = {
     294             :                 { "help", VERB_ANY, VERB_ANY, 0, help       },
     295             :                 { "tar",  2,        3,        0, import_tar },
     296             :                 { "raw",  2,        3,        0, import_raw },
     297             :                 {}
     298             :         };
     299             : 
     300           0 :         return dispatch_verb(argc, argv, verbs, NULL);
     301             : }
     302             : 
     303           4 : static int run(int argc, char *argv[]) {
     304             :         int r;
     305             : 
     306           4 :         setlocale(LC_ALL, "");
     307           4 :         log_parse_environment();
     308           4 :         log_open();
     309             : 
     310           4 :         r = parse_argv(argc, argv);
     311           4 :         if (r <= 0)
     312           4 :                 return 0;
     313             : 
     314           0 :         (void) ignore_signals(SIGPIPE, -1);
     315             : 
     316           0 :         return import_main(argc, argv);
     317             : }
     318             : 
     319           4 : DEFINE_MAIN_FUNCTION(run);

Generated by: LCOV version 1.14