From ac1065014bf3cbeb5f9ef4a121efc2e133510748 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 14 Feb 2018 11:58:21 -0800 Subject: [PATCH] scoutfs-utils: add stat -s option Lots of tests run scout stat and parse a single value. Give them an option to have the only output be that value so they don't have to pull it out of the output. Signed-off-by: Zach Brown --- utils/src/stat.c | 83 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 14 deletions(-) diff --git a/utils/src/stat.c b/utils/src/stat.c index 2def6cea..2ae1a91e 100644 --- a/utils/src/stat.c +++ b/utils/src/stat.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "sparse.h" #include "util.h" @@ -14,20 +16,75 @@ #include "ioctl.h" #include "cmd.h" +#define FIELD(f) { \ + .name = #f, \ + .offset = offsetof(struct scoutfs_ioctl_stat_more, f), \ +} + +static struct stat_more_field { + char *name; + size_t offset; +} fields[] = { + FIELD(meta_seq), + FIELD(data_seq), + FIELD(data_version), + FIELD(online_blocks), + FIELD(offline_blocks), + { NULL, } +}; + +#define for_each_field(f) \ + for (f = fields; f->name; f++) + +static struct option long_ops[] = { + { "single_field", 1, NULL, 's' }, + { NULL, 0, NULL, 0} +}; + static int stat_more_cmd(int argc, char **argv) { struct scoutfs_ioctl_stat_more stm; + struct stat_more_field *single = NULL; + struct stat_more_field *fi; + char *single_name = NULL; char *path; int ret; int fd; int i; + int c; - if (argc == 1) { + while ((c = getopt_long(argc, argv, "s:", long_ops, NULL)) != -1) { + switch (c) { + case 's': + single_name = strdup(optarg); + assert(single_name); + break; + case '?': + default: + return -EINVAL; + } + } + + if (single_name) { + for_each_field(fi) { + if (strcmp(fi->name, single_name) == 0) { + single = fi; + break; + } + } + if (!single) { + fprintf(stderr, "unknown stat_more field: '%s'\n", + single_name); + return -EINVAL; + } + } + + if (optind >= argc) { fprintf(stderr, "must specify at least one path argument\n"); return -EINVAL; } - for (i = 1; i < argc; i++) { + for (i = optind; i < argc; i++) { path = argv[i]; fd = open(path, O_RDONLY); @@ -46,19 +103,17 @@ static int stat_more_cmd(int argc, char **argv) ret = -errno; fprintf(stderr, "stat_more ioctl failed on '%s': " "%s (%d)\n", path, strerror(errno), errno); + + } else if (single) { + printf("%llu\n", + *(u64 *)((void *)&stm + single->offset)); + } else { - printf("path %s\n" - "meta_seq %llu\n" - "data_seq %llu\n" - "data_version %llu\n" - "online_blocks %llu\n" - "offline_blocks %llu\n", - path, - stm.meta_seq, - stm.data_seq, - stm.data_version, - stm.online_blocks, - stm.offline_blocks); + printf("%-17s %s\n", "path", path); + for_each_field(fi) { + printf("%-17s %llu\n", fi->name, + *(u64 *)((void *)&stm + fi->offset)); + } } close(fd);