]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: optionally mkdir directory to overmount
authorLennart Poettering <lennart@poettering.net>
Tue, 28 Jul 2020 16:50:17 +0000 (18:50 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 11 Aug 2020 20:26:48 +0000 (22:26 +0200)
src/dissect/dissect.c
src/shared/dissect-image.c
src/shared/dissect-image.h

index d0ae2a61d382e249abb5c19a2e55d569cacf624c..0384c2c3f063237d3364161cdb203578a2ef9ae3 100644 (file)
 #include "main-func.h"
 #include "parse-util.h"
 #include "path-util.h"
+#include "pretty-print.h"
 #include "string-util.h"
 #include "strv.h"
+#include "terminal-util.h"
 #include "user-util.h"
 #include "util.h"
 
@@ -37,15 +39,21 @@ STATIC_DESTRUCTOR_REGISTER(arg_verity_data, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root_hash_sig_path, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root_hash_sig, freep);
 
-static void help(void) {
-        printf("%s [OPTIONS...] IMAGE\n"
-               "%s [OPTIONS...] --mount IMAGE PATH\n"
-               "Dissect a file system OS image.\n\n"
-               "  -h --help               Show this help\n"
-               "     --version            Show package version\n"
-               "  -m --mount              Mount the image to the specified directory\n"
+static int help(void) {
+        _cleanup_free_ char *link = NULL;
+        int r;
+
+        r = terminal_urlify_man("systemd-dissect", "1", &link);
+        if (r < 0)
+                return log_oom();
+
+        printf("%1$s [OPTIONS...] IMAGE\n"
+               "%1$s [OPTIONS...] --mount IMAGE PATH\n\n"
+               "%5$sDissect a file system OS image.%6$s\n\n"
+               "%3$sOptions:%4$s\n"
                "  -r --read-only          Mount read-only\n"
                "     --fsck=BOOL          Run fsck before mounting\n"
+               "     --mkdir              Make mount directory before mounting, if missing\n"
                "     --discard=MODE       Choose 'discard' mode (disabled, loop, all, crypto)\n"
                "     --root-hash=HASH     Specify root hash for verity\n"
                "     --root-hash-sig=SIG  Specify pkcs7 signature of root hash for verity\n"
@@ -53,9 +61,19 @@ static void help(void) {
                "                          or as an ASCII base64 encoded string prefixed by\n"
                "                          'base64:'\n"
                "     --verity-data=PATH   Specify data file with hash tree for verity if it is\n"
-               "                          not embedded in IMAGE\n",
-               program_invocation_short_name,
-               program_invocation_short_name);
+               "                          not embedded in IMAGE\n"
+               "\n%3$sCommands:%4$s\n"
+               "  -h --help               Show this help\n"
+               "     --version            Show package version\n"
+               "  -m --mount              Mount the image to the specified directory\n"
+               "  -M                      Shortcut for --mount --mkdir\n"
+               "\nSee the %2$s for details.\n"
+               , program_invocation_short_name
+               , link
+               , ansi_underline(), ansi_normal()
+               , ansi_highlight(), ansi_normal());
+
+        return 0;
 }
 
 static int parse_argv(int argc, char *argv[]) {
@@ -67,6 +85,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_FSCK,
                 ARG_VERITY_DATA,
                 ARG_ROOT_HASH_SIG,
+                ARG_MKDIR,
         };
 
         static const struct option options[] = {
@@ -79,6 +98,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "fsck",          required_argument, NULL, ARG_FSCK          },
                 { "verity-data",   required_argument, NULL, ARG_VERITY_DATA   },
                 { "root-hash-sig", required_argument, NULL, ARG_ROOT_HASH_SIG },
+                { "mkdir",         no_argument,       NULL, ARG_MKDIR         },
                 {}
         };
 
@@ -87,13 +107,12 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hmr", options, NULL)) >= 0) {
+        while ((c = getopt_long(argc, argv, "hmrM", options, NULL)) >= 0) {
 
                 switch (c) {
 
                 case 'h':
-                        help();
-                        return 0;
+                        return help();
 
                 case ARG_VERSION:
                         return version();
@@ -102,6 +121,16 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_action = ACTION_MOUNT;
                         break;
 
+                case ARG_MKDIR:
+                        arg_flags |= DISSECT_IMAGE_MKDIR;
+                        break;
+
+                case 'M':
+                        /* Shortcut combination of the above two */
+                        arg_action = ACTION_MOUNT;
+                        arg_flags |= DISSECT_IMAGE_MKDIR;
+                        break;
+
                 case 'r':
                         arg_flags |= DISSECT_IMAGE_READ_ONLY;
                         break;
index d3f183b50c54cb3ac94034a86d761253dca1bb72..2b3d6c08f0c500092287f97588f93bd5bf107d1c 100644 (file)
@@ -1047,6 +1047,12 @@ static int mount_partition(
                 if (!strextend_with_separator(&options, ",", m->mount_options, NULL))
                         return -ENOMEM;
 
+        if (FLAGS_SET(flags, DISSECT_IMAGE_MKDIR)) {
+                r = mkdir_p(p, 0755);
+                if (r < 0)
+                        return r;
+        }
+
         r = mount_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options);
         if (r < 0)
                 return r;
@@ -1080,6 +1086,10 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
         if (flags & DISSECT_IMAGE_MOUNT_ROOT_ONLY)
                 return 0;
 
+        /* Mask DISSECT_IMAGE_MKDIR for all subdirs: the idea is that only the top-level mount point is
+         * created if needed, but the image itself not modified. */
+        flags &= ~DISSECT_IMAGE_MKDIR;
+
         r = mount_partition(m->partitions + PARTITION_HOME, where, "/home", uid_shift, flags);
         if (r < 0)
                 return r;
index 7f67c8745e858c4261d55883972ff3c0da489025..3d0a191d71b2128ecdade7e2e045be8b537c6cea 100644 (file)
@@ -69,6 +69,7 @@ typedef enum DissectImageFlags {
         DISSECT_IMAGE_FSCK                = 1 << 11, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */
         DISSECT_IMAGE_NO_PARTITION_TABLE  = 1 << 12, /* Only recognize single file system images */
         DISSECT_IMAGE_VERITY_SHARE        = 1 << 13, /* When activating a verity device, reuse existing one if already open */
+        DISSECT_IMAGE_MKDIR               = 1 << 14, /* Make directory to mount right before mounting, if missing */
 } DissectImageFlags;
 
 struct DissectedImage {