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