diff options
author | Luke Shumaker <lukeshu@beefcake.parabola.nu> | 2018-05-16 10:30:03 -0400 |
---|---|---|
committer | Luke Shumaker <lukeshu@beefcake.parabola.nu> | 2018-05-16 10:30:03 -0400 |
commit | 9891d6597770ed884c989885d04da46db5952f0a (patch) | |
tree | 133e1d8989ff26dd94f71602b71bb4d5ef803fc3 /src | |
parent | 94ee3156b7a22b02f8b21e6db3fcdf7d1ad51d0e (diff) |
first pass at cow-extent-map
Diffstat (limited to 'src')
-rw-r--r-- | src/cow-extent-map.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/cow-extent-map.c b/src/cow-extent-map.c new file mode 100644 index 0000000..7cee70c --- /dev/null +++ b/src/cow-extent-map.c @@ -0,0 +1,93 @@ +#define _GNU_SOURCE /* for program_invocation_name */ +#include <assert.h> /* for assert(3p) */ +#include <errno.h> /* for errno, program_invocation_name */ +#include <error.h> /* for error(3gnu) */ +#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 <stdio.h> /* for printf(3p), fprintf(3p), stderr */ +#include <stdlib.h> /* exit(3p), EXIT_SUCCESS, EXIT_FAILURE */ +#include <string.h> /* for strcmp(3p) */ + +#include "extent-map.h" /* for uint32_t, fiemap stuff */ + +#define EXIT_INVALIDARGUMENT 2 +#define errusage(format, ...) do { \ + error(0, 0, format, ## __VA_ARGS__); \ + fprintf(stderr, "Try '%s --help' for more information.\n", program_invocation_name); \ + exit(EXIT_INVALIDARGUMENT); \ +} while(0) + +int print_extent(struct fiemap_extent extent) { + printf("logical=%"PRIu64" " + "physical=%"PRIu64" " + "length=%"PRIu64" " + "flags=0x%"PRIx32"\n", + extent.fe_logical, + extent.fe_physical, + extent.fe_length, + extent.fe_flags); + return 0; +} + +void usage() { + printf("Usage: %s [OPTIONS] FILENAME\n" + "Print a file extent map.\n" + "\n" + "OPTIONS:\n" + " --stream=data Map extents in the data stream (default).\n" + " --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" + " -h, --help Display this help and exit.\n", + program_invocation_name); +} + +int main(int argc, char *argv[]) { + char *stream = "data"; + int sync = 1; + struct option long_options[] = { + {"stream", optional_argument, NULL, 1}, + {"sync", no_argument, &sync, 1}, + {"no-sync", no_argument, &sync, 0}, + {"help", no_argument, NULL, 'h'}, + {0}, + }; + int flag; + while ((flag = getopt_long(argc, argv, "h", long_options, NULL)) >= 0) { + switch (flag) { + case 0: + break; + case 1: + stream = optarg; + break; + case 'h': + usage(); + return EXIT_SUCCESS; + case '?': + fprintf(stderr, "Try '%s --help' for more information.\n", program_invocation_name); + return EXIT_INVALIDARGUMENT; + default: + assert(0); + } + } + if (argc - optind != 1) + errusage("wrong number of arguments"); + + uint32_t flags = sync ? FIEMAP_FLAG_SYNC : 0; + if (strcmp(stream, "data") == 0) { + /* do nothing */ + } else if (strcmp(stream, "xattr") == 0) { + flags |= FIEMAP_FLAG_XATTR; + } else { + errusage("invalid stream name"); + } + + char *filename = argv[optind]; + int fd = open(filename, O_RDONLY); + if (fd < 0) + error(EXIT_FAILURE, errno, "%s", filename); + + fiemap(fd, flags, print_extent); + return EXIT_SUCCESS;; +} |