coreutils
[Top][All Lists]
Advanced

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

Re: [coreutils] Re: [PATCH 2/2] stat: print timestamps to full resolutio


From: Jim Meyering
Subject: Re: [coreutils] Re: [PATCH 2/2] stat: print timestamps to full resolution
Date: Thu, 21 Oct 2010 16:01:21 +0200

Andreas Schwab wrote:
> Jim Meyering <address@hidden> writes:
>
>> And besides, with coreutils-8.6 already released, reverting the
>> change is no longer an option.
>
> Why?  I'm pretty sure more breakage will pop up over time.

Hmm... I see what you mean.
Anyone using a distribution with coreutils-8.5 or older will
think it's fine to treat $(stat -c %X) as an integer with no
decimal or trailing fraction.

Is it worthwhile to create a new format, say %...:X (and same for Y and Z)
that expands to seconds.nanoseconds and to revert %...X to the old
seconds-only semantics?

That would make it so people could use stat's %X %Y %Z portably
while new scripts can still get nanosecond accuracy when needed.

Here's PoC code:

  $ for i in %X %:X %Y %:Y %Z %:Z; do src/stat -c $i .; done
  1256665918
  1256665918.441784225
  1287476685
  1287476685.450022280
  1287476685
  1287476685.450022280

In retrospect, %W should get the same treatment.

diff --git a/src/stat.c b/src/stat.c
index fabbc17..dfb4dcb 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -463,7 +463,7 @@ human_time (struct timespec t)
 }

 static char * ATTRIBUTE_WARN_UNUSED_RESULT
-epoch_time (struct timespec t)
+epoch_time (bool print_ns, struct timespec t)
 {
   static char str[INT_STRLEN_BOUND (time_t) + sizeof ".NNNNNNNNN"];
   /* Note that time_t can technically be a floating point value, such
@@ -475,10 +475,20 @@ epoch_time (struct timespec t)
      converting to struct tm just to use nstrftime (str, len, "%s.%N",
      tm, 0, t.tv_nsec) is pointless, since nstrftime would have to
      convert back to seconds as time_t.  */
-  if (TYPE_SIGNED (time_t))
-    sprintf (str, "%" PRIdMAX ".%09ld", (intmax_t) t.tv_sec, t.tv_nsec);
+  if (print_ns)
+    {
+      if (TYPE_SIGNED (time_t))
+        sprintf (str, "%" PRIdMAX ".%09ld", (intmax_t) t.tv_sec, t.tv_nsec);
+      else
+        sprintf (str, "%" PRIuMAX ".%09ld", (uintmax_t) t.tv_sec, t.tv_nsec);
+    }
   else
-    sprintf (str, "%" PRIuMAX ".%09ld", (uintmax_t) t.tv_sec, t.tv_nsec);
+    {
+      if (TYPE_SIGNED (time_t))
+        sprintf (str, "%" PRIdMAX, (intmax_t) t.tv_sec);
+      else
+        sprintf (str, "%" PRIuMAX, (uintmax_t) t.tv_sec);
+    }
   return str;
 }

@@ -539,7 +549,8 @@ out_file_context (char *pformat, size_t prefix_len, char 
const *filename)

 /* Print statfs info.  Return zero upon success, nonzero upon failure.  */
 static bool ATTRIBUTE_WARN_UNUSED_RESULT
-print_statfs (char *pformat, size_t prefix_len, char m, char const *filename,
+print_statfs (char *pformat, size_t prefix_len, unsigned int m,
+              char const *filename,
               void const *data)
 {
   STRUCT_STATVFS const *statfsbuf = data;
@@ -713,7 +724,7 @@ print_mount_point:

 /* Print stat info.  Return zero upon success, nonzero upon failure.  */
 static bool
-print_stat (char *pformat, size_t prefix_len, char m,
+print_stat (char *pformat, size_t prefix_len, unsigned int m,
             char const *filename, void const *data)
 {
   struct stat *statbuf = (struct stat *) data;
@@ -820,26 +831,35 @@ print_stat (char *pformat, size_t prefix_len, char m,
         if (t.tv_nsec < 0)
           out_string (pformat, prefix_len, "-");
         else
-          out_string (pformat, prefix_len, epoch_time (t));
+          out_string (pformat, prefix_len, epoch_time (0, t));
       }
       break;
     case 'x':
       out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf)));
       break;
     case 'X':
-      out_string (pformat, prefix_len, epoch_time (get_stat_atime (statbuf)));
+      out_string (pformat, prefix_len, epoch_time (0, get_stat_atime 
(statbuf)));
+      break;
+    case 'X' + 256:
+      out_string (pformat, prefix_len, epoch_time (1, get_stat_atime 
(statbuf)));
       break;
     case 'y':
       out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf)));
       break;
     case 'Y':
-      out_string (pformat, prefix_len, epoch_time (get_stat_mtime (statbuf)));
+      out_string (pformat, prefix_len, epoch_time (0, get_stat_mtime 
(statbuf)));
+      break;
+    case 'Y' + 256:
+      out_string (pformat, prefix_len, epoch_time (1, get_stat_mtime 
(statbuf)));
       break;
     case 'z':
       out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf)));
       break;
     case 'Z':
-      out_string (pformat, prefix_len, epoch_time (get_stat_ctime (statbuf)));
+      out_string (pformat, prefix_len, epoch_time (0, get_stat_ctime 
(statbuf)));
+      break;
+    case 'Z' + 256:
+      out_string (pformat, prefix_len, epoch_time (1, get_stat_ctime 
(statbuf)));
       break;
     case 'C':
       fail |= out_file_context (pformat, prefix_len, filename);
@@ -897,7 +917,8 @@ print_esc_char (char c)
    Return zero upon success, nonzero upon failure.  */
 static bool ATTRIBUTE_WARN_UNUSED_RESULT
 print_it (char const *format, char const *filename,
-          bool (*print_func) (char *, size_t, char, char const *, void const 
*),
+          bool (*print_func) (char *, size_t, unsigned int,
+                              char const *, void const *),
           void const *data)
 {
   bool fail = false;
@@ -922,10 +943,21 @@ print_it (char const *format, char const *filename,
           {
             size_t len = strspn (b + 1, "#-+.I 0123456789");
             char const *fmt_char = b + len + 1;
+            unsigned int fmt_code;
             memcpy (dest, b, len + 1);

+            if (*fmt_char == ':' && strchr ("XYZ", fmt_char[1]))
+              {
+                fmt_code = fmt_char[1] + 256;
+                ++fmt_char;
+              }
+            else
+              {
+                fmt_code = fmt_char[0];
+              }
+
             b = fmt_char;
-            switch (*fmt_char)
+            switch (fmt_code)
               {
               case '\0':
                 --b;
@@ -941,7 +973,7 @@ print_it (char const *format, char const *filename,
                 putchar ('%');
                 break;
               default:
-                fail |= print_func (dest, len + 1, *fmt_char, filename, data);
+                fail |= print_func (dest, len + 1, fmt_code, filename, data);
                 break;
               }
             break;



reply via email to

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