coreutils
[Top][All Lists]
Advanced

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

[PATCH] stat: fallback if statx() is not available


From: Ville Heikkinen
Subject: [PATCH] stat: fallback if statx() is not available
Date: Tue, 8 Sep 2020 10:56:51 +0300

In case statx() returns EPERM or ENOSYS, fallback to use fstat(),
lstat() and stat() instead.

It's possible that the statx() is not functional e.g. due to the
used seccomp filters. Because of that, it would be good to fallback
to use the other methods to retrieve the stat info.
---
 src/stat.c | 37 +++++++++++++++++++++++++++++--------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/src/stat.c b/src/stat.c
index 4e6c2aa86..f53f98c3d 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -246,6 +246,10 @@ static char const *trailing_delim = "";
 static char const *decimal_point;
 static size_t decimal_point_len;
 
+#if USE_STATX
+static bool use_stat = false;
+#endif
+
 static bool
 print_stat (char *pformat, size_t prefix_len, unsigned int m,
             int fd, char const *filename, void const *data);
@@ -1329,9 +1333,13 @@ format_to_mask (char const *format)
   return mask;
 }
 
+static bool ATTRIBUTE_WARN_UNUSED_RESULT
+do_stat (char const *filename, char const *format,
+         char const *format2);
+
 /* 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)
+do_statx (char const *filename, char const *format, char const *format2)
 {
   int fd = STREQ (filename, "-") ? 0 : AT_FDCWD;
   int flags = 0;
@@ -1360,6 +1368,11 @@ do_stat (char const *filename, char const *format, char 
const *format2)
   fd = statx (fd, pathname, flags, format_to_mask (format), &stx);
   if (fd < 0)
     {
+      if (errno == EPERM || errno == ENOSYS)
+        {
+          use_stat = true;
+          return do_stat (filename, format, format2);
+        }
       if (flags & AT_EMPTY_PATH)
         error (0, errno, _("cannot stat standard input"));
       else
@@ -1378,7 +1391,7 @@ do_stat (char const *filename, char const *format, char 
const *format2)
   return ! fail;
 }
 
-#else /* USE_STATX */
+#endif /* USE_STATX */
 
 static struct timespec
 get_birthtime (int fd, char const *filename, struct stat const *st)
@@ -1449,7 +1462,6 @@ do_stat (char const *filename, char const *format,
   bool fail = print_it (format, fd, filename, print_stat, &pa);
   return ! fail;
 }
-#endif /* USE_STATX */
 
 
 /* Print stat info.  Return zero upon success, nonzero upon failure.  */
@@ -1548,9 +1560,10 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
int m,
       break;
     case 'w':
       {
-#if ! USE_STATX
-        btime = get_birthtime (fd, filename, statbuf);
+#if USE_STATX
+        if (use_stat)
 #endif
+          btime = get_birthtime (fd, filename, statbuf);
         if (btime.tv_nsec < 0)
           out_string (pformat, prefix_len, "-");
         else
@@ -1559,9 +1572,10 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
int m,
       break;
     case 'W':
       {
-#if ! USE_STATX
-        btime = get_birthtime (fd, filename, statbuf);
+#if USE_STATX
+        if (use_stat)
 #endif
+          btime = get_birthtime (fd, filename, statbuf);
         out_epoch_sec (pformat, prefix_len, neg_to_zero (btime));
       }
       break;
@@ -1903,7 +1917,14 @@ main (int argc, char *argv[])
   for (int i = optind; i < argc; i++)
     ok &= (fs
            ? do_statfs (argv[i], format)
-           : do_stat (argv[i], format, format2));
+#if USE_STATX
+           : (use_stat
+              ? do_stat (argv[i], format, format2)
+              : do_statx (argv[i], format, format2))
+#else
+           : do_stat (argv[i], format, format2)
+#endif
+           );
 
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-- 
2.26.2




reply via email to

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