* src/stat.c: Pass the btime into print_stat()
and reuse this function to print the (already transformed)
statx attributes.
---
 src/stat.c | 279 ++++++++++++++++++-------------------------------------------
 1 file changed, 82 insertions(+), 197 deletions(-)

diff --git a/src/stat.c b/src/stat.c
index 3e8f531..492daf3 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -243,6 +243,10 @@ static char const *trailing_delim = "";
 static char const *decimal_point;
 static size_t decimal_point_len;
 
+static bool
+print_stat (char *pformat, size_t prefix_len, unsigned int m,
+            int fd, char const *filename, void const *data);
+
 /* Return the type of the specified file system.
    Some systems have statfvs.f_basetype[FSTYPSZ] (AIX, HP-UX, and Solaris).
    Others have statvfs.f_fstypename[_VFS_NAMELEN] (NetBSD 3.0).
@@ -1227,6 +1231,11 @@ do_statfs (char const *filename, char const *format)
   return ! fail;
 }
 
+struct print_args {
+  struct stat *st;
+  struct timespec btime;
+};
+
 #if HAVE_STATX && defined STATX_INO
 /* Ask statx to avoid syncing? */
 static bool dont_sync;
@@ -1234,11 +1243,6 @@ static bool dont_sync;
 /* Ask statx to force sync? */
 static bool force_sync;
 
-struct printarg {
-  struct statx *stx;
-  struct stat *st;
-};
-
 /* Much of the format printing requires a struct stat or timespec */
 static struct timespec
 statx_timestamp_to_timespec (struct statx_timestamp tsx)
@@ -1259,151 +1263,17 @@ statx_to_stat (struct statx *stx, struct stat *stat)
   stat->st_nlink = stx->stx_nlink;
   stat->st_uid = stx->stx_uid;
   stat->st_gid = stx->stx_gid;
-  stat->st_dev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor);
+  stat->st_rdev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor);
   stat->st_size = stx->stx_size;
   stat->st_blksize = stx->stx_blksize;
-  /* Skip setting st_blocks to avoid sc_prohibit_stat_st_blocks warning */
+/* define to avoid sc_prohibit_stat_st_blocks.  */
+# define SC_ST_BLOCKS st_blocks
+  stat->SC_ST_BLOCKS = stx->stx_blocks;
   stat->st_atim = statx_timestamp_to_timespec (stx->stx_atime);
   stat->st_mtim = statx_timestamp_to_timespec (stx->stx_mtime);
   stat->st_ctim = statx_timestamp_to_timespec (stx->stx_ctime);
 }
 
-/* Print statx info.  Return zero upon success, nonzero upon failure.  */
-static bool
-print_statx (char *pformat, size_t prefix_len, unsigned int m,
-             int fd, char const *filename, void const *data)
-{
-  struct printarg *parg = (struct printarg *) data;
-  struct statx *stx = parg->stx;
-  struct stat *st = parg->st;
-  struct passwd *pw_ent;
-  struct group *gw_ent;
-  bool fail = false;
-
-  switch (m)
-    {
-    case 'n':
-      out_string (pformat, prefix_len, filename);
-      break;
-    case 'N':
-      out_string (pformat, prefix_len, quoteN (filename));
-      if (S_ISLNK (stx->stx_mode))
-        {
-          char *linkname = areadlink_with_size (filename, stx->stx_size);
-          if (linkname == NULL)
-            {
-              error (0, errno, _("cannot read symbolic link %s"),
-                     quoteaf (filename));
-              return true;
-            }
-          printf (" -> ");
-          out_string (pformat, prefix_len, quoteN (linkname));
-          free (linkname);
-        }
-      break;
-    case 'd':
-      out_uint (pformat, prefix_len, st->st_dev);
-      break;
-    case 'D':
-      out_uint_x (pformat, prefix_len, st->st_dev);
-      break;
-    case 'i':
-      out_uint (pformat, prefix_len, stx->stx_ino);
-      break;
-    case 'a':
-      out_uint_o (pformat, prefix_len, stx->stx_mode & CHMOD_MODE_BITS);
-      break;
-    case 'A':
-      out_string (pformat, prefix_len, human_access (st));
-      break;
-    case 'f':
-      out_uint_x (pformat, prefix_len, stx->stx_mode);
-      break;
-    case 'F':
-      out_string (pformat, prefix_len, file_type (st));
-      break;
-    case 'h':
-      out_uint (pformat, prefix_len, stx->stx_nlink);
-      break;
-    case 'u':
-      out_uint (pformat, prefix_len, stx->stx_uid);
-      break;
-    case 'U':
-      pw_ent = getpwuid (stx->stx_uid);
-      out_string (pformat, prefix_len,
-                  pw_ent ? pw_ent->pw_name : "UNKNOWN");
-      break;
-    case 'g':
-      out_uint (pformat, prefix_len, stx->stx_gid);
-      break;
-    case 'G':
-      gw_ent = getgrgid (stx->stx_gid);
-      out_string (pformat, prefix_len,
-                  gw_ent ? gw_ent->gr_name : "UNKNOWN");
-      break;
-    case 'm':
-      fail |= out_mount_point (filename, pformat, prefix_len, st);
-      break;
-    case 's':
-      out_int (pformat, prefix_len, stx->stx_size);
-      break;
-    case 't':
-      out_uint_x (pformat, prefix_len, stx->stx_rdev_major);
-      break;
-    case 'T':
-      out_uint_x (pformat, prefix_len, stx->stx_rdev_minor);
-      break;
-    case 'B':
-      out_uint (pformat, prefix_len, ST_NBLOCKSIZE);
-      break;
-    case 'b':
-      out_uint (pformat, prefix_len, stx->stx_blocks);
-      break;
-    case 'o':
-      out_uint (pformat, prefix_len, stx->stx_blksize);
-      break;
-    case 'w':
-      if (stx->stx_mask & STATX_BTIME)
-        out_string (pformat, prefix_len,
-                    human_time (statx_timestamp_to_timespec (stx->stx_btime)));
-      else
-        out_string (pformat, prefix_len, "-");
-      break;
-    case 'W':
-      if (stx->stx_mask & STATX_BTIME)
-        out_epoch_sec (pformat, prefix_len,
-                       statx_timestamp_to_timespec (stx->stx_btime));
-      else
-        out_string (pformat, prefix_len, "0");
-      break;
-    case 'x':
-      out_string (pformat, prefix_len, human_time (st->st_atim));
-      break;
-    case 'X':
-      out_epoch_sec (pformat, prefix_len, st->st_atim);
-      break;
-    case 'y':
-      out_string (pformat, prefix_len, human_time (st->st_mtim));
-      break;
-    case 'Y':
-      out_epoch_sec (pformat, prefix_len, st->st_mtim);
-      break;
-    case 'z':
-      out_string (pformat, prefix_len, human_time (st->st_ctim));
-      break;
-    case 'Z':
-      out_epoch_sec (pformat, prefix_len, st->st_ctim);
-      break;
-    case 'C':
-      fail |= out_file_context (pformat, prefix_len, filename);
-      break;
-    default:
-      fputc ('?', stdout);
-      break;
-    }
-  return fail;
-}
-
 static unsigned int
 fmt_to_mask (char fmt)
 {
@@ -1484,10 +1354,9 @@ do_stat (char const *filename, char const *format, char 
const *format2)
   struct stat st;
   struct statx stx;
   const char *pathname = filename;
-  struct printarg pa = {
-                         .stx = &stx,
-                         .st  = &st
-                       };
+  struct print_args pa;
+  pa.st = &st;
+  pa.btime = (struct timespec) {-1, -1};
 
   if (AT_FDCWD != fd)
     {
@@ -1510,20 +1379,23 @@ do_stat (char const *filename, char const *format, char 
const *format2)
       if (flags & AT_EMPTY_PATH)
         error (0, errno, _("cannot stat standard input"));
       else
-error (0, errno, _("cannot statx %s"), quoteaf (filename));
+        error (0, errno, _("cannot statx %s"), quoteaf (filename));
       return false;
     }
 
   if (S_ISBLK (stx.stx_mode) || S_ISCHR (stx.stx_mode))
     format = format2;
 
-  /* Many of the gnulib routines require a struct stat */
   statx_to_stat (&stx, &st);
+  if (stx.stx_mask & STATX_BTIME)
+    pa.btime = statx_timestamp_to_timespec (stx.stx_btime);
 
-  bool fail = print_it (format, fd, filename, print_statx, &pa);
+  bool fail = print_it (format, fd, filename, print_stat, &pa);
   return ! fail;
 }
+
 #else /* HAVE_STATX && defined STATX_INO */
+
 static struct timespec
 get_birthtime (int fd, char const *filename, struct stat const *st)
 {
@@ -1556,12 +1428,54 @@ get_birthtime (int fd, char const *filename, struct 
stat const *st)
   return ts;
 }
 
+
+/* stat the file and print what we find */
+static bool ATTRIBUTE_WARN_UNUSED_RESULT
+do_stat (char const *filename, char const *format,
+         char const *format2)
+{
+  int fd = STREQ (filename, "-") ? 0 : -1;
+  struct stat statbuf;
+  struct print_args pa;
+  pa.st = &statbuf;
+  pa.btime = (struct timespec) {-1, -1};
+
+  if (0 <= fd)
+    {
+      if (fstat (fd, &statbuf) != 0)
+        {
+          error (0, errno, _("cannot stat standard input"));
+          return false;
+        }
+    }
+  /* We can't use the shorter
+     (follow_links?stat:lstat) (filename, &statbug)
+     since stat might be a function-like macro.  */
+  else if ((follow_links
+            ? stat (filename, &statbuf)
+            : lstat (filename, &statbuf)) != 0)
+    {
+      error (0, errno, _("cannot stat %s"), quoteaf (filename));
+      return false;
+    }
+
+  if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode))
+    format = format2;
+
+  bool fail = print_it (format, fd, filename, print_stat, &pa);
+  return ! fail;
+}
+#endif /* HAVE_STATX && defined STATX_INO */
+
+
 /* Print stat info.  Return zero upon success, nonzero upon failure.  */
 static bool
 print_stat (char *pformat, size_t prefix_len, unsigned int m,
             int fd, char const *filename, void const *data)
 {
-  struct stat *statbuf = (struct stat *) data;
+  struct print_args *parg = (struct print_args *) data;
+  struct stat *statbuf = parg->st;
+  struct timespec btime = parg->btime;
   struct passwd *pw_ent;
   struct group *gw_ent;
   bool fail = false;
@@ -1627,18 +1541,18 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
int m,
       out_string (pformat, prefix_len,
                   gw_ent ? gw_ent->gr_name : "UNKNOWN");
       break;
-    case 't':
-      out_uint_x (pformat, prefix_len, major (statbuf->st_rdev));
-      break;
     case 'm':
       fail |= out_mount_point (filename, pformat, prefix_len, statbuf);
       break;
-    case 'T':
-      out_uint_x (pformat, prefix_len, minor (statbuf->st_rdev));
-      break;
     case 's':
       out_int (pformat, prefix_len, statbuf->st_size);
       break;
+    case 't':
+      out_uint_x (pformat, prefix_len, major (statbuf->st_rdev));
+      break;
+    case 'T':
+      out_uint_x (pformat, prefix_len, minor (statbuf->st_rdev));
+      break;
     case 'B':
       out_uint (pformat, prefix_len, ST_NBLOCKSIZE);
       break;
@@ -1650,16 +1564,22 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
int m,
       break;
     case 'w':
       {
-        struct timespec t = get_birthtime (fd, filename, statbuf);
-        if (t.tv_nsec < 0)
+#if ! defined HAVE_STATX || ! defined STATX_INO
+        btime = get_birthtime (fd, filename, statbuf);
+#endif
+        if (btime.tv_nsec < 0)
           out_string (pformat, prefix_len, "-");
         else
-          out_string (pformat, prefix_len, human_time (t));
+          out_string (pformat, prefix_len, human_time (btime));
       }
       break;
     case 'W':
-      out_epoch_sec (pformat, prefix_len,
-                     neg_to_zero (get_birthtime (fd, filename, statbuf)));
+      {
+#if ! defined HAVE_STATX || ! defined STATX_INO
+        btime = get_birthtime (fd, filename, statbuf);
+#endif
+        out_epoch_sec (pformat, prefix_len, neg_to_zero (btime));
+      }
       break;
     case 'x':
       out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf)));
@@ -1689,41 +1609,6 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
int m,
   return fail;
 }
 
-/* stat the file and print what we find */
-static bool ATTRIBUTE_WARN_UNUSED_RESULT
-do_stat (char const *filename, char const *format,
-         char const *format2)
-{
-  int fd = STREQ (filename, "-") ? 0 : -1;
-  struct stat statbuf;
-
-  if (0 <= fd)
-    {
-      if (fstat (fd, &statbuf) != 0)
-        {
-          error (0, errno, _("cannot stat standard input"));
-          return false;
-        }
-    }
-  /* We can't use the shorter
-     (follow_links?stat:lstat) (filename, &statbug)
-     since stat might be a function-like macro.  */
-  else if ((follow_links
-            ? stat (filename, &statbuf)
-            : lstat (filename, &statbuf)) != 0)
-    {
-      error (0, errno, _("cannot stat %s"), quoteaf (filename));
-      return false;
-    }
-
-  if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode))
-    format = format2;
-
-  bool fail = print_it (format, fd, filename, print_stat, &statbuf);
-  return ! fail;
-}
-#endif /* HAVE_STATX && defined STATX_INO */
-
 /* Return an allocated format string in static storage that
    corresponds to whether FS and TERSE options were declared.  */
 static char *
-- 
2.9.3


Reply via email to