From 02442af0aec2d75aaab73cd605519eddfbe07a29 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 18 May 2018 13:08:11 -0400 Subject: cow-extent-map: allow multiple files, machine output --- src/cow-extent-map.c | 50 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/src/cow-extent-map.c b/src/cow-extent-map.c index aeedadf..6e7ee57 100644 --- a/src/cow-extent-map.c +++ b/src/cow-extent-map.c @@ -5,6 +5,7 @@ #include /* for open(2) and O_RDONLY */ #include /* for getopt_long(3gnu), struct option, optind, optarg */ #include /* PRI* */ +#include /* for bool, true, false */ #include /* for printf(3p), fprintf(3p), stderr */ #include /* free(3p), exit(3p), EXIT_SUCCESS, EXIT_FAILURE */ #include /* for strcmp(3p) */ @@ -18,12 +19,16 @@ exit(EXIT_INVALIDARGUMENT); \ } while(0) +bool indent; + int print_extent(struct fiemap_extent extent) { char *flagstr = strextentflags(extent.fe_flags); - printf("logical=%"PRIu64" " + printf("%s" + "logical=%"PRIu64" " "physical=%"PRIu64" " "length=%"PRIu64" " "flags=0x%08"PRIx32" (%s)\n", + indent ? "\t" : "", extent.fe_logical, extent.fe_physical, extent.fe_length, @@ -34,7 +39,7 @@ int print_extent(struct fiemap_extent extent) { } void usage() { - printf("Usage: %s [OPTIONS] FILENAME\n" + printf("Usage: %s [OPTIONS] FILENAME...\n" "Print a file extent map.\n" "\n" "OPTIONS:\n" @@ -42,12 +47,14 @@ void usage() { " --stream=xattr Map extents in the extended attribute stream.\n" " --sync Sync the file before mapping extents (default).\n" " --no-sync Don't sync the file before mapping extents.\n" + " -m, --machine Display the output in a more machine-friendly format.\n" " -h, --help Display this help and exit.\n", program_invocation_name); } int main(int argc, char *argv[]) { char *stream = "data"; + bool machine = false; int sync = 1; struct option long_options[] = { {"stream", optional_argument, NULL, 1}, @@ -57,13 +64,16 @@ int main(int argc, char *argv[]) { {0}, }; int flag; - while ((flag = getopt_long(argc, argv, "h", long_options, NULL)) >= 0) { + while ((flag = getopt_long(argc, argv, "mh", long_options, NULL)) >= 0) { switch (flag) { case 0: break; case 1: stream = optarg; break; + case 'm': + machine = true; + break; case 'h': usage(); return EXIT_SUCCESS; @@ -74,7 +84,7 @@ int main(int argc, char *argv[]) { assert(0); } } - if (argc - optind != 1) + if (argc - optind < 1) errusage("wrong number of arguments"); uint32_t flags = sync ? FIEMAP_FLAG_SYNC : 0; @@ -86,10 +96,32 @@ int main(int argc, char *argv[]) { errusage("invalid stream name"); } - char *filename = argv[optind]; - int fd = open(filename, O_RDONLY); - if (fd < 0) - error(EXIT_FAILURE, errno, "%s", filename); + indent = (argc - optind) > 1 && !machine; + + int status = 0; + for (int i = optind; i < argc; i++) { + char *filename = argv[i]; + if (machine) { + printf("%s", filename); + putchar('\0'); + } else if (argc - optind > 1) + printf("%s:\n", filename); + int fd = open(filename, O_RDONLY); + if (fd < 0) { + error(0, errno, "%s", filename); + status |= EXIT_FAILURE; + continue; + } - return fiemap(fd, flags, print_extent); + int r = fiemap(fd, flags, print_extent); + if (r < 0) { + error(0, -r, "%s: FS_IOC_FIEMAP", filename); + status |= EXIT_FAILURE; + } else { + status |= r; + } + if (machine) + putchar('\0'); + } + return status; } -- cgit v1.2.3