]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: add --list option
authorAntonio Alvarez Feijoo <antonio.feijoo@suse.com>
Thu, 20 Oct 2022 06:07:37 +0000 (08:07 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Mon, 31 Oct 2022 20:11:09 +0000 (21:11 +0100)
New option to print the paths of all the files and directories in the image to
stdout.

man/systemd-dissect.xml
shell-completion/bash/systemd-dissect
src/dissect/dissect.c

index 9528e91a41c8bf8a1be7417e97dcbe8b7a5f4b78..955909ff914220e0282471ba2b30b7bc38d4e7b9 100644 (file)
@@ -31,6 +31,9 @@
     <cmdsynopsis>
       <command>systemd-dissect <arg choice="opt" rep="repeat">OPTIONS</arg> <option>--umount</option> <arg choice="plain"><replaceable>PATH</replaceable></arg></command>
     </cmdsynopsis>
+    <cmdsynopsis>
+      <command>systemd-dissect <arg choice="opt" rep="repeat">OPTIONS</arg> <option>--list</option> <arg choice="plain"><replaceable>IMAGE</replaceable></arg></command>
+    </cmdsynopsis>
     <cmdsynopsis>
       <command>systemd-dissect <arg choice="opt" rep="repeat">OPTIONS</arg> <option>--copy-from</option> <arg choice="plain"><replaceable>IMAGE</replaceable></arg> <arg choice="plain"><replaceable>PATH</replaceable></arg> <arg choice="opt"><replaceable>TARGET</replaceable></arg></command>
     </cmdsynopsis>
         <listitem><para>This is a shortcut for <option>--umount --rmdir</option>.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--list</option></term>
+        <term><option>-l</option></term>
+
+        <listitem><para>Prints the paths of all the files and directories in the specified OS image to
+        standard output.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--copy-from</option></term>
         <term><option>-x</option></term>
index 5e1ce05e72c9200f0f1f42fef36cf4eb9418438f..275ef6ba8d604e68c4cde062eb49480d3c284b26 100644 (file)
@@ -35,6 +35,7 @@ _systemd_dissect() {
                      --rmdir'
         [ARG]='-m --mount -M
                -u --umount -U
+               -l --list
                -x --copy-from
                -a --copy-to
                --fsck
@@ -50,7 +51,7 @@ _systemd_dissect() {
 
     if __contains_word "$prev_1" ${OPTS[ARG]}; then
         case $prev_1 in
-            -m|--mount|-M|-x|--copy-from|-a|--copy-to|--verity-data)
+            -l|--list|-m|--mount|-M|-x|--copy-from|-a|--copy-to|--verity-data)
                 comps=$(compgen -A file -- "$cur")
                 compopt -o filenames
                 ;;
index c465115fc700e4ff50dd3f43f5e4fb82389dba46..de46dad5861b1f883d5b40b63229fc14a350a501 100644 (file)
@@ -35,6 +35,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "pretty-print.h"
+#include "recurse-dir.h"
 #include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
@@ -47,6 +48,7 @@ static enum {
         ACTION_DISSECT,
         ACTION_MOUNT,
         ACTION_UMOUNT,
+        ACTION_LIST,
         ACTION_COPY_FROM,
         ACTION_COPY_TO,
 } arg_action = ACTION_DISSECT;
@@ -80,6 +82,7 @@ static int help(void) {
         printf("%1$s [OPTIONS...] IMAGE\n"
                "%1$s [OPTIONS...] --mount IMAGE PATH\n"
                "%1$s [OPTIONS...] --umount PATH\n"
+               "%1$s [OPTIONS...] --list IMAGE\n"
                "%1$s [OPTIONS...] --copy-from IMAGE PATH [TARGET]\n"
                "%1$s [OPTIONS...] --copy-to IMAGE [SOURCE] PATH\n\n"
                "%5$sDissect a Discoverable Disk Image (DDI).%6$s\n\n"
@@ -108,6 +111,8 @@ static int help(void) {
                "  -M                      Shortcut for --mount --mkdir\n"
                "  -u --umount             Unmount the image from the specified directory\n"
                "  -U                      Shortcut for --umount --rmdir\n"
+               "  -l --list               List all the files and directories of the specified\n"
+               "                          OS image\n"
                "  -x --copy-from          Copy files from image to host\n"
                "  -a --copy-to            Copy files from host to image\n"
                "\nSee the %2$s for details.\n",
@@ -154,6 +159,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "verity-data",   required_argument, NULL, ARG_VERITY_DATA   },
                 { "mkdir",         no_argument,       NULL, ARG_MKDIR         },
                 { "rmdir",         no_argument,       NULL, ARG_RMDIR         },
+                { "list",          no_argument,       NULL, 'l'               },
                 { "copy-from",     no_argument,       NULL, 'x'               },
                 { "copy-to",       no_argument,       NULL, 'a'               },
                 { "json",          required_argument, NULL, ARG_JSON          },
@@ -165,7 +171,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hmurMUxa", options, NULL)) >= 0) {
+        while ((c = getopt_long(argc, argv, "hmurMUlxa", options, NULL)) >= 0) {
 
                 switch (c) {
 
@@ -211,6 +217,11 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_rmdir = true;
                         break;
 
+                case 'l':
+                        arg_action = ACTION_LIST;
+                        arg_flags |= DISSECT_IMAGE_READ_ONLY;
+                        break;
+
                 case 'x':
                         arg_action = ACTION_COPY_FROM;
                         arg_flags |= DISSECT_IMAGE_READ_ONLY;
@@ -353,6 +364,15 @@ static int parse_argv(int argc, char *argv[]) {
                 arg_path = argv[optind];
                 break;
 
+        case ACTION_LIST:
+                if (optind + 1 != argc)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "Expected an image file path as only argument.");
+
+                arg_image = argv[optind];
+                arg_flags |= DISSECT_IMAGE_READ_ONLY | DISSECT_IMAGE_REQUIRE_ROOT;
+                break;
+
         case ACTION_COPY_FROM:
                 if (argc < optind + 2 || argc > optind + 3)
                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@@ -685,7 +705,26 @@ static int action_mount(DissectedImage *m, LoopDevice *d) {
         return 0;
 }
 
-static int action_copy(DissectedImage *m, LoopDevice *d) {
+static int list_print_item(
+                RecurseDirEvent event,
+                const char *path,
+                int dir_fd,
+                int inode_fd,
+                const struct dirent *de,
+                const struct statx *sx,
+                void *userdata) {
+
+        assert_se(path);
+
+        if (event == RECURSE_DIR_ENTER)
+                printf("%s/\n", path);
+        else if (event == RECURSE_DIR_ENTRY)
+                printf("%s\n", path);
+
+        return RECURSE_DIR_CONTINUE;
+}
+
+static int action_list_or_copy(DissectedImage *m, LoopDevice *d) {
         _cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
         _cleanup_(rmdir_and_freep) char *created_dir = NULL;
         _cleanup_free_ char *temp = NULL;
@@ -774,13 +813,11 @@ static int action_copy(DissectedImage *m, LoopDevice *d) {
 
                 /* When this is a regular file we don't copy ownership! */
 
-        } else {
+        } else if (arg_action == ACTION_COPY_TO) {
                 _cleanup_close_ int source_fd = -1, target_fd = -1;
                 _cleanup_close_ int dfd = -1;
                 _cleanup_free_ char *dn = NULL;
 
-                assert(arg_action == ACTION_COPY_TO);
-
                 r = path_extract_directory(arg_target, &dn);
                 if (r < 0)
                         return log_error_errno(r, "Failed to extract directory name from target path '%s': %m", arg_target);
@@ -842,6 +879,20 @@ static int action_copy(DissectedImage *m, LoopDevice *d) {
                 (void) copy_times(source_fd, target_fd, 0);
 
                 /* When this is a regular file we don't copy ownership! */
+
+        } else {
+                _cleanup_close_ int dfd = -1;
+                _cleanup_strv_free_ char **list_dir = NULL;
+
+                assert(arg_action == ACTION_LIST);
+
+                dfd = open(mounted_dir, O_DIRECTORY|O_CLOEXEC|O_RDONLY);
+                if (dfd < 0)
+                        return log_error_errno(errno, "Failed to open mount directory: %m");
+
+                r = recurse_dir(dfd, NULL, 0, UINT_MAX, RECURSE_DIR_SORT|RECURSE_DIR_ENSURE_TYPE|RECURSE_DIR_SAME_MOUNT, list_print_item, &list_dir);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to list image: %m");
         }
 
         return 0;
@@ -961,9 +1012,10 @@ static int run(int argc, char *argv[]) {
                 r = action_mount(m, d);
                 break;
 
+        case ACTION_LIST:
         case ACTION_COPY_FROM:
         case ACTION_COPY_TO:
-                r = action_copy(m, d);
+                r = action_list_or_copy(m, d);
                 break;
 
         default: