summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd-dissect.xml11
-rw-r--r--shell-completion/bash/systemd-dissect3
-rw-r--r--src/dissect/dissect.c64
3 files changed, 71 insertions, 7 deletions
diff --git a/man/systemd-dissect.xml b/man/systemd-dissect.xml
index 9528e91a41..955909ff91 100644
--- a/man/systemd-dissect.xml
+++ b/man/systemd-dissect.xml
@@ -32,6 +32,9 @@
<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>
<cmdsynopsis>
@@ -150,6 +153,14 @@
</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>
diff --git a/shell-completion/bash/systemd-dissect b/shell-completion/bash/systemd-dissect
index 5e1ce05e72..275ef6ba8d 100644
--- a/shell-completion/bash/systemd-dissect
+++ b/shell-completion/bash/systemd-dissect
@@ -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
;;
diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c
index c465115fc7..de46dad586 100644
--- a/src/dissect/dissect.c
+++ b/src/dissect/dissect.c
@@ -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: