coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v3 3/4] stat: only set STATX_* mask bits for things we want to pr


From: Jeff Layton
Subject: [PATCH v3 3/4] stat: only set STATX_* mask bits for things we want to print
Date: Tue, 16 Apr 2019 17:22:42 -0400

Scan the format string to build a STATX_* mask prior to calling statx.
This allows us to avoid setting bits for attributes that we don't
intend to display, which can mean a much lighter-weight operation on
some filesystems.

* src/stat.c: only set STATX_* mask bits for things we want to print
---
 src/stat.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 79 insertions(+), 2 deletions(-)

diff --git a/src/stat.c b/src/stat.c
index 264e9138cdc9..2bbc75792b5a 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -1370,6 +1370,84 @@ print_statx (char *pformat, size_t prefix_len, unsigned 
int m,
   return fail;
 }
 
+static unsigned int
+fmt_to_mask(char fmt)
+{
+  switch(fmt)
+    {
+    case 'N':
+      return STATX_MODE|STATX_SIZE;
+    case 'd':
+    case 'D':
+      return STATX_MODE;
+    case 'i':
+      return STATX_INO;
+    case 'a':
+    case 'A':
+      return STATX_MODE;
+    case 'f':
+      return STATX_MODE|STATX_TYPE;
+    case 'F':
+      return STATX_TYPE;
+    case 'h':
+      return STATX_NLINK;
+    case 'u':
+    case 'U':
+      return STATX_UID;
+    case 'g':
+    case 'G':
+      return STATX_GID;
+    case 'm':
+      return STATX_MODE|STATX_INO;
+    case 's':
+      return STATX_SIZE;
+    case 't':
+    case 'T':
+      return STATX_MODE;
+    case 'b':
+      return STATX_BLOCKS;
+    case 'w':
+    case 'W':
+      return STATX_BTIME;
+    case 'x':
+    case 'X':
+      return STATX_ATIME;
+    case 'y':
+    case 'Y':
+      return STATX_MTIME;
+    case 'z':
+    case 'Z':
+      return STATX_CTIME;
+    }
+  return 0;
+}
+
+static unsigned int __attribute__((const))
+format_to_mask(char const *format)
+{
+  unsigned int mask = 0;
+  char const *b;
+
+  for (b = format; *b; b++)
+    {
+      if (*b != '%')
+       continue;
+
+      size_t len = strspn (b + 1, printf_flags);
+      char const *fmt_char = b + len + 1;
+      fmt_char += strspn (fmt_char, digits);
+      if (*fmt_char == '.')
+        fmt_char += 1 + strspn (fmt_char + 1, digits);
+      char fmt_code = *fmt_char;
+
+      b = fmt_char;
+      if (fmt_code == '\0')
+       break;
+      mask |= fmt_to_mask(fmt_code);
+    }
+  return mask;
+}
+
 /* statx the file and print what we find */
 static bool ATTRIBUTE_WARN_UNUSED_RESULT
 do_stat (char const *filename, char const *format, char const *format2)
@@ -1394,8 +1472,7 @@ do_stat (char const *filename, char const *format, char 
const *format2)
       flags = AT_SYMLINK_NOFOLLOW;
     }
 
-  /* FIXME: set request mask based on format */
-  fd = statx(fd, pathname, flags, STATX_BASIC_STATS|STATX_BTIME, &stx);
+  fd = statx(fd, pathname, flags, format_to_mask(format), &stx);
   if (fd < 0)
     {
       if (flags & AT_EMPTY_PATH)
-- 
2.20.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]