summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@beefcake.parabola.nu>2018-05-18 13:08:11 -0400
committerLuke Shumaker <lukeshu@beefcake.parabola.nu>2018-05-18 13:08:11 -0400
commit02442af0aec2d75aaab73cd605519eddfbe07a29 (patch)
treeb37226129d36eec22f3fb2169a5a1c41a08720b3
parent1e13f3671739e98f4e6d8531b9b22c93d24589f8 (diff)
cow-extent-map: allow multiple files, machine output
-rw-r--r--src/cow-extent-map.c50
1 files 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 <fcntl.h> /* for open(2) and O_RDONLY */
#include <getopt.h> /* for getopt_long(3gnu), struct option, optind, optarg */
#include <inttypes.h> /* PRI* */
+#include <stdbool.h> /* for bool, true, false */
#include <stdio.h> /* for printf(3p), fprintf(3p), stderr */
#include <stdlib.h> /* free(3p), exit(3p), EXIT_SUCCESS, EXIT_FAILURE */
#include <string.h> /* 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;
}