LCOV - code coverage report
Current view: top level - dissect - dissect.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 24 138 17.4 %
Date: 2019-08-22 15:41:25 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <fcntl.h>
       4             : #include <stdio.h>
       5             : #include <getopt.h>
       6             : 
       7             : #include "architecture.h"
       8             : #include "dissect-image.h"
       9             : #include "hexdecoct.h"
      10             : #include "log.h"
      11             : #include "loop-util.h"
      12             : #include "main-func.h"
      13             : #include "string-util.h"
      14             : #include "strv.h"
      15             : #include "user-util.h"
      16             : #include "util.h"
      17             : 
      18             : static enum {
      19             :         ACTION_DISSECT,
      20             :         ACTION_MOUNT,
      21             : } arg_action = ACTION_DISSECT;
      22             : static const char *arg_image = NULL;
      23             : static const char *arg_path = NULL;
      24             : static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP;
      25             : static void *arg_root_hash = NULL;
      26             : static size_t arg_root_hash_size = 0;
      27             : 
      28           4 : STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep);
      29             : 
      30           3 : static void help(void) {
      31           3 :         printf("%s [OPTIONS...] IMAGE\n"
      32             :                "%s [OPTIONS...] --mount IMAGE PATH\n"
      33             :                "Dissect a file system OS image.\n\n"
      34             :                "  -h --help            Show this help\n"
      35             :                "     --version         Show package version\n"
      36             :                "  -m --mount           Mount the image to the specified directory\n"
      37             :                "  -r --read-only       Mount read-only\n"
      38             :                "     --discard=MODE    Choose 'discard' mode (disabled, loop, all, crypto)\n"
      39             :                "     --root-hash=HASH  Specify root hash for verity\n",
      40             :                program_invocation_short_name,
      41             :                program_invocation_short_name);
      42           3 : }
      43             : 
      44           4 : static int parse_argv(int argc, char *argv[]) {
      45             : 
      46             :         enum {
      47             :                 ARG_VERSION = 0x100,
      48             :                 ARG_DISCARD,
      49             :                 ARG_ROOT_HASH,
      50             :         };
      51             : 
      52             :         static const struct option options[] = {
      53             :                 { "help",      no_argument,       NULL, 'h'           },
      54             :                 { "version",   no_argument,       NULL, ARG_VERSION   },
      55             :                 { "mount",     no_argument,       NULL, 'm'           },
      56             :                 { "read-only", no_argument,       NULL, 'r'           },
      57             :                 { "discard",   required_argument, NULL, ARG_DISCARD   },
      58             :                 { "root-hash", required_argument, NULL, ARG_ROOT_HASH },
      59             :                 {}
      60             :         };
      61             : 
      62             :         int c, r;
      63             : 
      64           4 :         assert(argc >= 0);
      65           4 :         assert(argv);
      66             : 
      67           4 :         while ((c = getopt_long(argc, argv, "hmr", options, NULL)) >= 0) {
      68             : 
      69           4 :                 switch (c) {
      70             : 
      71           3 :                 case 'h':
      72           3 :                         help();
      73           3 :                         return 0;
      74             : 
      75           0 :                 case ARG_VERSION:
      76           0 :                         return version();
      77             : 
      78           0 :                 case 'm':
      79           0 :                         arg_action = ACTION_MOUNT;
      80           0 :                         break;
      81             : 
      82           0 :                 case 'r':
      83           0 :                         arg_flags |= DISSECT_IMAGE_READ_ONLY;
      84           0 :                         break;
      85             : 
      86           0 :                 case ARG_DISCARD: {
      87             :                         DissectImageFlags flags;
      88             : 
      89           0 :                         if (streq(optarg, "disabled"))
      90           0 :                                 flags = 0;
      91           0 :                         else if (streq(optarg, "loop"))
      92           0 :                                 flags = DISSECT_IMAGE_DISCARD_ON_LOOP;
      93           0 :                         else if (streq(optarg, "all"))
      94           0 :                                 flags = DISSECT_IMAGE_DISCARD_ON_LOOP | DISSECT_IMAGE_DISCARD;
      95           0 :                         else if (streq(optarg, "crypt"))
      96           0 :                                 flags = DISSECT_IMAGE_DISCARD_ANY;
      97             :                         else
      98           0 :                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
      99             :                                                        "Unknown --discard= parameter: %s",
     100             :                                                        optarg);
     101           0 :                         arg_flags = (arg_flags & ~DISSECT_IMAGE_DISCARD_ANY) | flags;
     102             : 
     103           0 :                         break;
     104             :                 }
     105             : 
     106           0 :                 case ARG_ROOT_HASH: {
     107             :                         void *p;
     108             :                         size_t l;
     109             : 
     110           0 :                         r = unhexmem(optarg, strlen(optarg), &p, &l);
     111           0 :                         if (r < 0)
     112           0 :                                 return log_error_errno(r, "Failed to parse root hash '%s': %m", optarg);
     113           0 :                         if (l < sizeof(sd_id128_t)) {
     114           0 :                                 log_error("Root hash must be at least 128bit long: %s", optarg);
     115           0 :                                 free(p);
     116           0 :                                 return -EINVAL;
     117             :                         }
     118             : 
     119           0 :                         free(arg_root_hash);
     120           0 :                         arg_root_hash = p;
     121           0 :                         arg_root_hash_size = l;
     122           0 :                         break;
     123             :                 }
     124             : 
     125           1 :                 case '?':
     126           1 :                         return -EINVAL;
     127             : 
     128           0 :                 default:
     129           0 :                         assert_not_reached("Unhandled option");
     130             :                 }
     131             : 
     132             :         }
     133             : 
     134           0 :         switch (arg_action) {
     135             : 
     136           0 :         case ACTION_DISSECT:
     137           0 :                 if (optind + 1 != argc)
     138           0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     139             :                                                "Expected a file path as only argument.");
     140             : 
     141           0 :                 arg_image = argv[optind];
     142           0 :                 arg_flags |= DISSECT_IMAGE_READ_ONLY;
     143           0 :                 break;
     144             : 
     145           0 :         case ACTION_MOUNT:
     146           0 :                 if (optind + 2 != argc)
     147           0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     148             :                                                "Expected a file path and mount point path as only arguments.");
     149             : 
     150           0 :                 arg_image = argv[optind];
     151           0 :                 arg_path = argv[optind + 1];
     152           0 :                 break;
     153             : 
     154           0 :         default:
     155           0 :                 assert_not_reached("Unknown action.");
     156             :         }
     157             : 
     158           0 :         return 1;
     159             : }
     160             : 
     161           4 : static int run(int argc, char *argv[]) {
     162           4 :         _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
     163           4 :         _cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL;
     164           4 :         _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
     165             :         int r;
     166             : 
     167           4 :         log_parse_environment();
     168           4 :         log_open();
     169             : 
     170           4 :         r = parse_argv(argc, argv);
     171           4 :         if (r <= 0)
     172           4 :                 return r;
     173             : 
     174           0 :         r = loop_device_make_by_path(arg_image, (arg_flags & DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR, &d);
     175           0 :         if (r < 0)
     176           0 :                 return log_error_errno(r, "Failed to set up loopback device: %m");
     177             : 
     178           0 :         if (!arg_root_hash) {
     179           0 :                 r = root_hash_load(arg_image, &arg_root_hash, &arg_root_hash_size);
     180           0 :                 if (r < 0)
     181           0 :                         return log_error_errno(r, "Failed to read root hash file for %s: %m", arg_image);
     182             :         }
     183             : 
     184           0 :         r = dissect_image_and_warn(d->fd, arg_image, arg_root_hash, arg_root_hash_size, arg_flags, &m);
     185           0 :         if (r < 0)
     186           0 :                 return r;
     187             : 
     188           0 :         switch (arg_action) {
     189             : 
     190           0 :         case ACTION_DISSECT: {
     191             :                 unsigned i;
     192             : 
     193           0 :                 for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
     194           0 :                         DissectedPartition *p = m->partitions + i;
     195             :                         int k;
     196             : 
     197           0 :                         if (!p->found)
     198           0 :                                 continue;
     199             : 
     200           0 :                         printf("Found %s '%s' partition",
     201           0 :                                p->rw ? "writable" : "read-only",
     202             :                                partition_designator_to_string(i));
     203             : 
     204           0 :                         if (!sd_id128_is_null(p->uuid))
     205           0 :                                 printf(" (UUID " SD_ID128_FORMAT_STR ")", SD_ID128_FORMAT_VAL(p->uuid));
     206             : 
     207           0 :                         if (p->fstype)
     208           0 :                                 printf(" of type %s", p->fstype);
     209             : 
     210           0 :                         if (p->architecture != _ARCHITECTURE_INVALID)
     211           0 :                                 printf(" for %s", architecture_to_string(p->architecture));
     212             : 
     213           0 :                         k = PARTITION_VERITY_OF(i);
     214           0 :                         if (k >= 0)
     215           0 :                                 printf(" %s verity", m->partitions[k].found ? "with" : "without");
     216             : 
     217           0 :                         if (p->partno >= 0)
     218           0 :                                 printf(" on partition #%i", p->partno);
     219             : 
     220           0 :                         if (p->node)
     221           0 :                                 printf(" (%s)", p->node);
     222             : 
     223           0 :                         putchar('\n');
     224             :                 }
     225             : 
     226           0 :                 r = dissected_image_acquire_metadata(m);
     227           0 :                 if (r < 0)
     228           0 :                         return log_error_errno(r, "Failed to acquire image metadata: %m");
     229             : 
     230           0 :                 if (m->hostname)
     231           0 :                         printf("  Hostname: %s\n", m->hostname);
     232             : 
     233           0 :                 if (!sd_id128_is_null(m->machine_id))
     234           0 :                         printf("Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(m->machine_id));
     235             : 
     236           0 :                 if (!strv_isempty(m->machine_info)) {
     237             :                         char **p, **q;
     238             : 
     239           0 :                         STRV_FOREACH_PAIR(p, q, m->machine_info)
     240           0 :                                 printf("%s %s=%s\n",
     241           0 :                                        p == m->machine_info ? "Mach. Info:" : "           ",
     242             :                                        *p, *q);
     243             :                 }
     244             : 
     245           0 :                 if (!strv_isempty(m->os_release)) {
     246             :                         char **p, **q;
     247             : 
     248           0 :                         STRV_FOREACH_PAIR(p, q, m->os_release)
     249           0 :                                 printf("%s %s=%s\n",
     250           0 :                                        p == m->os_release ? "OS Release:" : "           ",
     251             :                                        *p, *q);
     252             :                 }
     253             : 
     254           0 :                 break;
     255             :         }
     256             : 
     257           0 :         case ACTION_MOUNT:
     258           0 :                 r = dissected_image_decrypt_interactively(m, NULL, arg_root_hash, arg_root_hash_size, arg_flags, &di);
     259           0 :                 if (r < 0)
     260           0 :                         return r;
     261             : 
     262           0 :                 r = dissected_image_mount(m, arg_path, UID_INVALID, arg_flags);
     263           0 :                 if (r < 0)
     264           0 :                         return log_error_errno(r, "Failed to mount image: %m");
     265             : 
     266           0 :                 if (di) {
     267           0 :                         r = decrypted_image_relinquish(di);
     268           0 :                         if (r < 0)
     269           0 :                                 return log_error_errno(r, "Failed to relinquish DM devices: %m");
     270             :                 }
     271             : 
     272           0 :                 loop_device_relinquish(d);
     273           0 :                 break;
     274             : 
     275           0 :         default:
     276           0 :                 assert_not_reached("Unknown action.");
     277             :         }
     278             : 
     279           0 :         return 0;
     280             : }
     281             : 
     282           4 : DEFINE_MAIN_FUNCTION(run);

Generated by: LCOV version 1.14