]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_io: make statx mask parsing more generally useful
authorDarrick J. Wong <djwong@kernel.org>
Thu, 24 Apr 2025 21:53:39 +0000 (14:53 -0700)
committerAndrey Albershteyn <aalbersh@kernel.org>
Mon, 28 Apr 2025 10:56:58 +0000 (12:56 +0200)
Enhance the statx -m parsing to be more useful:

Add words for all the new STATX_* field flags added in the previous
patch.

Allow "+" and "-" prefixes to add or remove flags from the mask.

Allow multiple arguments to be specified as a comma separated list.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Andrey Albershteyn <aalbersh@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
io/stat.c
man/man8/xfs_io.8

index 52e2d33010a99a2f4853288b880fa2f68818efb7..c3a4bb15229ee5c6324717c7c77d167159ee9c01 100644 (file)
--- a/io/stat.c
+++ b/io/stat.c
@@ -321,10 +321,41 @@ _statx(
 #endif
 }
 
+struct statx_masks {
+       const char      *name;
+       unsigned int    mask;
+};
+
+static const struct statx_masks statx_masks[] = {
+       {"basic",               STATX_BASIC_STATS},
+       {"all",                 ~STATX__RESERVED},
+
+       {"type",                STATX_TYPE},
+       {"mode",                STATX_MODE},
+       {"nlink",               STATX_NLINK},
+       {"uid",                 STATX_UID},
+       {"gid",                 STATX_GID},
+       {"atime",               STATX_ATIME},
+       {"mtime",               STATX_MTIME},
+       {"ctime",               STATX_CTIME},
+       {"ino",                 STATX_INO},
+       {"size",                STATX_SIZE},
+       {"blocks",              STATX_BLOCKS},
+       {"btime",               STATX_BTIME},
+       {"mnt_id",              STATX_MNT_ID},
+       {"dioalign",            STATX_DIOALIGN},
+       {"mnt_id_unique",       STATX_MNT_ID_UNIQUE},
+       {"subvol",              STATX_SUBVOL},
+       {"write_atomic",        STATX_WRITE_ATOMIC},
+       {"dio_read_align",      STATX_DIO_READ_ALIGN},
+};
+
 static void
 statx_help(void)
 {
-        printf(_(
+       unsigned int    i;
+
+       printf(_(
 "\n"
 " Display extended file status.\n"
 "\n"
@@ -334,9 +365,16 @@ statx_help(void)
 " -m mask -- Specify the field mask for the statx call\n"
 "            (can also be 'basic' or 'all'; defaults to\n"
 "             STATX_BASIC_STATS | STATX_BTIME)\n"
+" -m +mask -- Add this to the field mask for the statx call\n"
+" -m -mask -- Remove this from the field mask for the statx call\n"
 " -D -- Don't sync attributes with the server\n"
 " -F -- Force the attributes to be sync'd with the server\n"
-"\n"));
+"\n"
+"statx mask values: "));
+
+       for (i = 0; i < ARRAY_SIZE(statx_masks); i++)
+               printf("%s%s", i == 0 ? "" : ", ", statx_masks[i].name);
+       printf("\n");
 }
 
 /* statx helper */
@@ -377,6 +415,68 @@ dump_raw_statx(struct statx *stx)
        return 0;
 }
 
+enum statx_mask_op {
+       SET,
+       REMOVE,
+       ADD,
+};
+
+static bool
+parse_statx_masks(
+       char                    *optarg,
+       unsigned int            *caller_mask)
+{
+       char                    *arg = optarg;
+       char                    *word;
+       unsigned int            i;
+
+       while ((word = strtok(arg, ",")) != NULL) {
+               enum statx_mask_op op;
+               unsigned int    mask;
+               char            *p;
+
+               arg = NULL;
+
+               if (*word == '+') {
+                       op = ADD;
+                       word++;
+               } else if (*word == '-') {
+                       op = REMOVE;
+                       word++;
+               } else {
+                       op = SET;
+               }
+
+               for (i = 0; i < ARRAY_SIZE(statx_masks); i++) {
+                       if (!strcmp(statx_masks[i].name, word)) {
+                               mask = statx_masks[i].mask;
+                               goto process_op;
+                       }
+               }
+
+               mask = strtoul(word, &p, 0);
+               if (!p || p == word) {
+                       printf( _("non-numeric mask -- %s\n"), word);
+                       return false;
+               }
+
+process_op:
+               switch (op) {
+               case ADD:
+                       *caller_mask |= mask;
+                       continue;
+               case REMOVE:
+                       *caller_mask &= ~mask;
+                       continue;
+               case SET:
+                       *caller_mask = mask;
+                       continue;
+               }
+       }
+
+       return true;
+}
+
 /*
  * options:
  *     - input flags - query type
@@ -389,7 +489,6 @@ statx_f(
        char            **argv)
 {
        int             c, verbose = 0, raw = 0;
-       char            *p;
        struct statx    stx;
        int             atflag = 0;
        unsigned int    mask = STATX_BASIC_STATS | STATX_BTIME;
@@ -397,18 +496,9 @@ statx_f(
        while ((c = getopt(argc, argv, "m:rvFD")) != EOF) {
                switch (c) {
                case 'm':
-                       if (strcmp(optarg, "basic") == 0)
-                               mask = STATX_BASIC_STATS;
-                       else if (strcmp(optarg, "all") == 0)
-                               mask = ~STATX__RESERVED;
-                       else {
-                               mask = strtoul(optarg, &p, 0);
-                               if (!p || p == optarg) {
-                                       printf(
-                               _("non-numeric mask -- %s\n"), optarg);
-                                       exitcode = 1;
-                                       return 0;
-                               }
+                       if (!parse_statx_masks(optarg, &mask)) {
+                               exitcode = 1;
+                               return 0;
                        }
                        break;
                case 'r':
index 198215103812c6b39f0bac5513974f9c5de55d22..64b3e907553f488fffbe701c8f6a7355c022142d 100644 (file)
@@ -1000,6 +1000,17 @@ The default is to set STATX_BASIC_STATS and STATX_BTIME.
 .B \-m <mask>
 Specify a numeric field mask for the statx call.
 .TP
+.BI "\-m +" value
+Add this value to the statx field value.
+Values can be numeric, or they can be words describing the desired fields.
+See the help command output for a list of recognized words.
+.TP
+.BI "\-m -" value
+Remove this value from the statx field value.
+.TP
+.BI "\-m +" value ",-" value
+Add and remove multiple values from the statx field value.
+.TP
 .B \-F
 Force the attributes to be synced with the server.
 .TP