LCOV - code coverage report
Current view: top level - import - export.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 20 161 12.4 %
Date: 2019-08-23 13:36:53 Functions: 4 11 36.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 6 131 4.6 %

           Branch data     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 "export-raw.h"
      11                 :            : #include "export-tar.h"
      12                 :            : #include "fd-util.h"
      13                 :            : #include "fs-util.h"
      14                 :            : #include "hostname-util.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 ImportCompressType arg_compress = IMPORT_COMPRESS_UNKNOWN;
      23                 :            : 
      24                 :          0 : static void determine_compression_from_filename(const char *p) {
      25                 :            : 
      26         [ #  # ]:          0 :         if (arg_compress != IMPORT_COMPRESS_UNKNOWN)
      27                 :          0 :                 return;
      28                 :            : 
      29         [ #  # ]:          0 :         if (!p) {
      30                 :          0 :                 arg_compress = IMPORT_COMPRESS_UNCOMPRESSED;
      31                 :          0 :                 return;
      32                 :            :         }
      33                 :            : 
      34         [ #  # ]:          0 :         if (endswith(p, ".xz"))
      35                 :          0 :                 arg_compress = IMPORT_COMPRESS_XZ;
      36         [ #  # ]:          0 :         else if (endswith(p, ".gz"))
      37                 :          0 :                 arg_compress = IMPORT_COMPRESS_GZIP;
      38         [ #  # ]:          0 :         else if (endswith(p, ".bz2"))
      39                 :          0 :                 arg_compress = IMPORT_COMPRESS_BZIP2;
      40                 :            :         else
      41                 :          0 :                 arg_compress = IMPORT_COMPRESS_UNCOMPRESSED;
      42                 :            : }
      43                 :            : 
      44                 :          0 : static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
      45         [ #  # ]:          0 :         log_notice("Transfer aborted.");
      46                 :          0 :         sd_event_exit(sd_event_source_get_event(s), EINTR);
      47                 :          0 :         return 0;
      48                 :            : }
      49                 :            : 
      50                 :          0 : static void on_tar_finished(TarExport *export, int error, void *userdata) {
      51                 :          0 :         sd_event *event = userdata;
      52         [ #  # ]:          0 :         assert(export);
      53                 :            : 
      54         [ #  # ]:          0 :         if (error == 0)
      55         [ #  # ]:          0 :                 log_info("Operation completed successfully.");
      56                 :            : 
      57                 :          0 :         sd_event_exit(event, abs(error));
      58                 :          0 : }
      59                 :            : 
      60                 :          0 : static int export_tar(int argc, char *argv[], void *userdata) {
      61                 :          0 :         _cleanup_(tar_export_unrefp) TarExport *export = NULL;
      62                 :          0 :         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
      63                 :          0 :         _cleanup_(image_unrefp) Image *image = NULL;
      64                 :          0 :         const char *path = NULL, *local = NULL;
      65                 :          0 :         _cleanup_close_ int open_fd = -1;
      66                 :            :         int r, fd;
      67                 :            : 
      68         [ #  # ]:          0 :         if (machine_name_is_valid(argv[1])) {
      69                 :          0 :                 r = image_find(IMAGE_MACHINE, argv[1], &image);
      70         [ #  # ]:          0 :                 if (r == -ENOENT)
      71         [ #  # ]:          0 :                         return log_error_errno(r, "Machine image %s not found.", argv[1]);
      72         [ #  # ]:          0 :                 if (r < 0)
      73         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to look for machine %s: %m", argv[1]);
      74                 :            : 
      75                 :          0 :                 local = image->path;
      76                 :            :         } else
      77                 :          0 :                 local = argv[1];
      78                 :            : 
      79         [ #  # ]:          0 :         if (argc >= 3)
      80                 :          0 :                 path = argv[2];
      81                 :          0 :         path = empty_or_dash_to_null(path);
      82                 :            : 
      83                 :          0 :         determine_compression_from_filename(path);
      84                 :            : 
      85         [ #  # ]:          0 :         if (path) {
      86                 :          0 :                 open_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666);
      87         [ #  # ]:          0 :                 if (open_fd < 0)
      88         [ #  # ]:          0 :                         return log_error_errno(errno, "Failed to open tar image for export: %m");
      89                 :            : 
      90                 :          0 :                 fd = open_fd;
      91                 :            : 
      92         [ #  # ]:          0 :                 log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, path, import_compress_type_to_string(arg_compress));
      93                 :            :         } else {
      94                 :          0 :                 _cleanup_free_ char *pretty = NULL;
      95                 :            : 
      96                 :          0 :                 fd = STDOUT_FILENO;
      97                 :            : 
      98                 :          0 :                 (void) fd_get_path(fd, &pretty);
      99         [ #  # ]:          0 :                 log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, strna(pretty), import_compress_type_to_string(arg_compress));
     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_export_new(&export, event, on_tar_finished, event);
     111         [ #  # ]:          0 :         if (r < 0)
     112         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to allocate exporter: %m");
     113                 :            : 
     114                 :          0 :         r = tar_export_start(export, local, fd, arg_compress);
     115         [ #  # ]:          0 :         if (r < 0)
     116         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to export 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(RawExport *export, int error, void *userdata) {
     127                 :          0 :         sd_event *event = userdata;
     128         [ #  # ]:          0 :         assert(export);
     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 export_raw(int argc, char *argv[], void *userdata) {
     137                 :          0 :         _cleanup_(raw_export_unrefp) RawExport *export = NULL;
     138                 :          0 :         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
     139                 :          0 :         _cleanup_(image_unrefp) Image *image = NULL;
     140                 :          0 :         const char *path = NULL, *local = NULL;
     141                 :          0 :         _cleanup_close_ int open_fd = -1;
     142                 :            :         int r, fd;
     143                 :            : 
     144         [ #  # ]:          0 :         if (machine_name_is_valid(argv[1])) {
     145                 :          0 :                 r = image_find(IMAGE_MACHINE, argv[1], &image);
     146         [ #  # ]:          0 :                 if (r == -ENOENT)
     147         [ #  # ]:          0 :                         return log_error_errno(r, "Machine image %s not found.", argv[1]);
     148         [ #  # ]:          0 :                 if (r < 0)
     149         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to look for machine %s: %m", argv[1]);
     150                 :            : 
     151                 :          0 :                 local = image->path;
     152                 :            :         } else
     153                 :          0 :                 local = argv[1];
     154                 :            : 
     155         [ #  # ]:          0 :         if (argc >= 3)
     156                 :          0 :                 path = argv[2];
     157                 :          0 :         path = empty_or_dash_to_null(path);
     158                 :            : 
     159                 :          0 :         determine_compression_from_filename(path);
     160                 :            : 
     161         [ #  # ]:          0 :         if (path) {
     162                 :          0 :                 open_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666);
     163         [ #  # ]:          0 :                 if (open_fd < 0)
     164         [ #  # ]:          0 :                         return log_error_errno(errno, "Failed to open raw image for export: %m");
     165                 :            : 
     166                 :          0 :                 fd = open_fd;
     167                 :            : 
     168         [ #  # ]:          0 :                 log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, path, import_compress_type_to_string(arg_compress));
     169                 :            :         } else {
     170                 :          0 :                 _cleanup_free_ char *pretty = NULL;
     171                 :            : 
     172                 :          0 :                 fd = STDOUT_FILENO;
     173                 :            : 
     174                 :          0 :                 (void) fd_get_path(fd, &pretty);
     175         [ #  # ]:          0 :                 log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, strna(pretty), import_compress_type_to_string(arg_compress));
     176                 :            :         }
     177                 :            : 
     178                 :          0 :         r = sd_event_default(&event);
     179         [ #  # ]:          0 :         if (r < 0)
     180         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to allocate event loop: %m");
     181                 :            : 
     182         [ #  # ]:          0 :         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
     183                 :          0 :         (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler,  NULL);
     184                 :          0 :         (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
     185                 :            : 
     186                 :          0 :         r = raw_export_new(&export, event, on_raw_finished, event);
     187         [ #  # ]:          0 :         if (r < 0)
     188         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to allocate exporter: %m");
     189                 :            : 
     190                 :          0 :         r = raw_export_start(export, local, fd, arg_compress);
     191         [ #  # ]:          0 :         if (r < 0)
     192         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to export image: %m");
     193                 :            : 
     194                 :          0 :         r = sd_event_loop(event);
     195         [ #  # ]:          0 :         if (r < 0)
     196         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to run event loop: %m");
     197                 :            : 
     198         [ #  # ]:          0 :         log_info("Exiting.");
     199                 :          0 :         return -r;
     200                 :            : }
     201                 :            : 
     202                 :         12 : static int help(int argc, char *argv[], void *userdata) {
     203                 :            : 
     204                 :         12 :         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
     205                 :            :                "Export container or virtual machine images.\n\n"
     206                 :            :                "  -h --help                    Show this help\n"
     207                 :            :                "     --version                 Show package version\n"
     208                 :            :                "     --format=FORMAT           Select format\n\n"
     209                 :            :                "Commands:\n"
     210                 :            :                "  tar NAME [FILE]              Export a TAR image\n"
     211                 :            :                "  raw NAME [FILE]              Export a RAW image\n",
     212                 :            :                program_invocation_short_name);
     213                 :            : 
     214                 :         12 :         return 0;
     215                 :            : }
     216                 :            : 
     217                 :         16 : static int parse_argv(int argc, char *argv[]) {
     218                 :            : 
     219                 :            :         enum {
     220                 :            :                 ARG_VERSION = 0x100,
     221                 :            :                 ARG_FORMAT,
     222                 :            :         };
     223                 :            : 
     224                 :            :         static const struct option options[] = {
     225                 :            :                 { "help",    no_argument,       NULL, 'h'         },
     226                 :            :                 { "version", no_argument,       NULL, ARG_VERSION },
     227                 :            :                 { "format",  required_argument, NULL, ARG_FORMAT  },
     228                 :            :                 {}
     229                 :            :         };
     230                 :            : 
     231                 :            :         int c;
     232                 :            : 
     233         [ -  + ]:         16 :         assert(argc >= 0);
     234         [ -  + ]:         16 :         assert(argv);
     235                 :            : 
     236         [ +  - ]:         16 :         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
     237                 :            : 
     238   [ +  -  -  +  :         16 :                 switch (c) {
                      - ]
     239                 :            : 
     240                 :         12 :                 case 'h':
     241                 :         12 :                         return help(0, NULL, NULL);
     242                 :            : 
     243                 :          0 :                 case ARG_VERSION:
     244                 :          0 :                         return version();
     245                 :            : 
     246                 :          0 :                 case ARG_FORMAT:
     247         [ #  # ]:          0 :                         if (streq(optarg, "uncompressed"))
     248                 :          0 :                                 arg_compress = IMPORT_COMPRESS_UNCOMPRESSED;
     249         [ #  # ]:          0 :                         else if (streq(optarg, "xz"))
     250                 :          0 :                                 arg_compress = IMPORT_COMPRESS_XZ;
     251         [ #  # ]:          0 :                         else if (streq(optarg, "gzip"))
     252                 :          0 :                                 arg_compress = IMPORT_COMPRESS_GZIP;
     253         [ #  # ]:          0 :                         else if (streq(optarg, "bzip2"))
     254                 :          0 :                                 arg_compress = IMPORT_COMPRESS_BZIP2;
     255                 :            :                         else
     256         [ #  # ]:          0 :                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     257                 :            :                                                        "Unknown format: %s", optarg);
     258                 :          0 :                         break;
     259                 :            : 
     260                 :          4 :                 case '?':
     261                 :          4 :                         return -EINVAL;
     262                 :            : 
     263                 :          0 :                 default:
     264                 :          0 :                         assert_not_reached("Unhandled option");
     265                 :            :                 }
     266                 :            : 
     267                 :          0 :         return 1;
     268                 :            : }
     269                 :            : 
     270                 :          0 : static int export_main(int argc, char *argv[]) {
     271                 :            :         static const Verb verbs[] = {
     272                 :            :                 { "help", VERB_ANY, VERB_ANY, 0, help       },
     273                 :            :                 { "tar",  2,        3,        0, export_tar },
     274                 :            :                 { "raw",  2,        3,        0, export_raw },
     275                 :            :                 {}
     276                 :            :         };
     277                 :            : 
     278                 :          0 :         return dispatch_verb(argc, argv, verbs, NULL);
     279                 :            : }
     280                 :            : 
     281                 :         16 : static int run(int argc, char *argv[]) {
     282                 :            :         int r;
     283                 :            : 
     284                 :         16 :         setlocale(LC_ALL, "");
     285                 :         16 :         log_parse_environment();
     286                 :         16 :         log_open();
     287                 :            : 
     288                 :         16 :         r = parse_argv(argc, argv);
     289         [ +  - ]:         16 :         if (r <= 0)
     290                 :         16 :                 return r;
     291                 :            : 
     292                 :          0 :         (void) ignore_signals(SIGPIPE, -1);
     293                 :            : 
     294                 :          0 :         return export_main(argc, argv);
     295                 :            : }
     296                 :            : 
     297                 :         16 : DEFINE_MAIN_FUNCTION(run);

Generated by: LCOV version 1.14