GNU bug report logs - #7325
new test failure due to non-portability of printf formats like %05.3s

Previous Next

Package: coreutils;

Reported by: Jim Meyering <jim <at> meyering.net>

Date: Wed, 3 Nov 2010 18:56:02 UTC

Severity: normal

Done: Pádraig Brady <P <at> draigBrady.com>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 7325 in the body.
You can then email your comments to 7325 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Wed, 03 Nov 2010 18:56:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Jim Meyering <jim <at> meyering.net>:
New bug report received and forwarded. Copy sent to bug-coreutils <at> gnu.org. (Wed, 03 Nov 2010 18:56:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: bug-coreutils <at> gnu.org
Subject: new test failure due to non-portability of printf formats like %05.3s
Date: Wed, 03 Nov 2010 19:59:44 +0100
At least on Solaris 10, the new stat-nanoseconds test fails,
due to non-portability of snprintf vs a format like %010.3s:

    FAIL: misc/stat-nanoseconds
    ...
    + touch -d '2010-10-21 18:43:33.023456789' k
    ...
    ++ stat -c %05.3:X k
    + test 00023 = '  023'
    + fail=1

You can demonstrate it with bash's built-in printf, too:

    solaris$ bash -c "printf '%010.3s\n' 23"
    0000000023

    glibc$ bash -c "printf '%010.3s\n' 23"
            23

Note that coreutils' printf does not accept the '0' modifier in a %s format.

    $ env printf '%05.3s\n' 23
    printf: %05.3s: invalid conversion specification

That's because POSIX says the "0" modifier applies only to the
d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversion specifiers.

One solution is to trim off the "0".
It's probably a good idea regardless, in case some implementation rejects it.

On the other hand, I find the zero-padding you currently get
with stat on solaris to be slightly more intuitive.
I'll sleep on it.

Other opinions welcome, as usual.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Wed, 03 Nov 2010 19:24:01 GMT) Full text and rfc822 format available.

Message #8 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Eric Blake <eblake <at> redhat.com>
To: Jim Meyering <jim <at> meyering.net>
Cc: 7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Wed, 03 Nov 2010 13:27:45 -0600
[Message part 1 (text/plain, inline)]
On 11/03/2010 12:59 PM, Jim Meyering wrote:
> Note that coreutils' printf does not accept the '0' modifier in a %s format.
> 
>     $ env printf '%05.3s\n' 23
>     printf: %05.3s: invalid conversion specification
> 
> That's because POSIX says the "0" modifier applies only to the
> d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversion specifiers.
> 
> One solution is to trim off the "0".
> It's probably a good idea regardless, in case some implementation rejects it.
> 
> On the other hand, I find the zero-padding you currently get
> with stat on solaris to be slightly more intuitive.

I agree that %05.3:X resulting in 00023 would be ideal.  And I agree
that we'd have to trim off the 0 modifier before calling the underlying
printf %s, and thus be responsible for putting in '0' padding ourselves
rather than relying on printf() padding.

-- 
Eric Blake   eblake <at> redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

[signature.asc (application/pgp-signature, attachment)]

Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Wed, 03 Nov 2010 21:23:01 GMT) Full text and rfc822 format available.

Message #11 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Eric Blake <eblake <at> redhat.com>
Cc: 7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Wed, 03 Nov 2010 22:26:40 +0100
Eric Blake wrote:
> On 11/03/2010 12:59 PM, Jim Meyering wrote:
>> Note that coreutils' printf does not accept the '0' modifier in a %s format.
>>
>>     $ env printf '%05.3s\n' 23
>>     printf: %05.3s: invalid conversion specification
>>
>> That's because POSIX says the "0" modifier applies only to the
>> d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversion specifiers.
>>
>> One solution is to trim off the "0".
>> It's probably a good idea regardless, in case some implementation rejects it.
>>
>> On the other hand, I find the zero-padding you currently get
>> with stat on solaris to be slightly more intuitive.
>
> I agree that %05.3:X resulting in 00023 would be ideal.  And I agree
> that we'd have to trim off the 0 modifier before calling the underlying
> printf %s, and thus be responsible for putting in '0' padding ourselves
> rather than relying on printf() padding.

Thanks for confirming.
Here's the patch I'm considering:

diff --git a/src/stat.c b/src/stat.c
index d05a93b..993db48 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -472,6 +472,23 @@ epoch_sec (struct timespec t)
   return timetostr (t.tv_sec, str);
 }

+/* Convert a LEN-byte FORMAT modifier, e.g., "0009.4", to "9.4".
+   Do it in place and return the new length.  */
+static size_t
+sanitize_format_string (char *format, size_t len)
+{
+  char *p = format;
+  char const *end = format + len;
+  while (p < end && *p == '0')
+    p++;
+  if (p == format)
+    return len;
+
+  len -= p - format;
+  memmove (format, p, len);
+  return len;
+}
+
 /* Output the number of nanoseconds, ARG.tv_nsec, honoring a
    WIDTH.PRECISION format modifier, where PRECISION specifies
    how many leading digits(on a field of 9) to print.  */
@@ -496,8 +513,25 @@ out_ns (char *pformat, size_t prefix_len, struct timespec arg)
     {
       char tmp[INT_BUFSIZE_BOUND (uintmax_t)];
       snprintf (tmp, sizeof tmp, "%09lu", ns);
+      /* Handle formats like %5.3:X and %05.3:X, which, with the likes of
+         "023" in TMP, should print "  023" and "00023" respectively.
+         Do not use a format like "%05s" with *printf, since POSIX says
+         the '0' modifier does not apply to the "s" conversion specifier.  */
+      size_t new_len = sanitize_format_string (pformat + 1, prefix_len - 1);
+      bool zero_pad = (new_len < prefix_len - 1);
+      prefix_len = new_len + 1;
       strcpy (pformat + prefix_len, "s");
-      printf (pformat, tmp);
+      char b2[INT_BUFSIZE_BOUND (uintmax_t)];
+      /* Format the result, as usual...  */
+      snprintf (b2, sizeof b2, pformat, tmp);
+      /* But if zero-padding is desired, convert leading blanks to zeros.  */
+      if (zero_pad)
+        {
+          char *p = b2;
+          while (*p == ' ')
+            *p++ = '0';
+        }
+      fputs (b2, stdout);
     }
   else
     {
diff --git a/tests/misc/stat-nanoseconds b/tests/misc/stat-nanoseconds
index 314f43e..9c06a51 100755
--- a/tests/misc/stat-nanoseconds
+++ b/tests/misc/stat-nanoseconds
@@ -30,7 +30,7 @@ test "$(stat -c   %3.3:X k)" = 023        || fail=1
 test "$(stat -c    %.3:X k)" = 023        || fail=1
 test "$(stat -c  %03.3:X k)" = 023        || fail=1
 test "$(stat -c  %-5.3:X k)" = '023  '    || fail=1
-test "$(stat -c  %05.3:X k)" = '  023'    || fail=1
-test "$(stat -c %010.3:X k)" = '       023' || fail=1
+test "$(stat -c  %05.3:X k)" = 00023      || fail=1
+test "$(stat -c %010.3:X k)" = 0000000023 || fail=1

 Exit $fail




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Wed, 03 Nov 2010 21:29:01 GMT) Full text and rfc822 format available.

Message #14 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Eric Blake <eblake <at> redhat.com>
To: Jim Meyering <jim <at> meyering.net>
Cc: 7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Wed, 03 Nov 2010 15:32:55 -0600
[Message part 1 (text/plain, inline)]
On 11/03/2010 03:26 PM, Jim Meyering wrote:
>> I agree that %05.3:X resulting in 00023 would be ideal.  And I agree
>> that we'd have to trim off the 0 modifier before calling the underlying
>> printf %s, and thus be responsible for putting in '0' padding ourselves
>> rather than relying on printf() padding.
> 
> Thanks for confirming.
> Here's the patch I'm considering:
> 
> diff --git a/src/stat.c b/src/stat.c
> index d05a93b..993db48 100644
> --- a/src/stat.c
> +++ b/src/stat.c
> @@ -472,6 +472,23 @@ epoch_sec (struct timespec t)
>    return timetostr (t.tv_sec, str);
>  }
> 
> +/* Convert a LEN-byte FORMAT modifier, e.g., "0009.4", to "9.4".
> +   Do it in place and return the new length.  */
> +static size_t
> +sanitize_format_string (char *format, size_t len)
> +{
> +  char *p = format;
> +  char const *end = format + len;
> +  while (p < end && *p == '0')
> +    p++;
> +  if (p == format)
> +    return len;
> +
> +  len -= p - format;
> +  memmove (format, p, len);
> +  return len;
> +}

Not just leading zeros.  Think also about "%-0 010.4:X", which must
sanitize to "%- 10.4s" - that is, you must strip any zero until the
first non-zero digit or '.' is found.

-- 
Eric Blake   eblake <at> redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

[signature.asc (application/pgp-signature, attachment)]

Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Wed, 03 Nov 2010 22:55:02 GMT) Full text and rfc822 format available.

Message #17 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Jim Meyering <jim <at> meyering.net>
Cc: 7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Wed, 03 Nov 2010 15:58:25 -0700
The test-case part of that looks OK, but the change to stat.c
can be simplified.  Also, there's a similar problem with a format
like %020X, which should be fixed too.

While we're on the subject, there are other ways that stat invokers
can exercise undefined behavior (in the C sense) by passing
weird formats in.  This really should get fixed at some point.
The patch proposed below addresses just the immediate issue.

From a24a9ce8f3711670a6413c60b5e9ebd3e51a4e06 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert <at> cs.ucla.edu>
Date: Wed, 3 Nov 2010 15:49:50 -0700
Subject: [PATCH] stat: handle leading '0' when formatting secs and ns

* src/stat.c (epoch_sec): Remove. All callers changed to use
out_epoch_sec instead.
(out_ns): Use numeric format, not string format, to output
the nanoseconds count; this avoids unportable use of (e.g.)
%05s in a printf format.
(out_epoch_sec): New function.  This also uses a numeric format,
instead of a string format, to output a number.
---
 src/stat.c |   56 ++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/src/stat.c b/src/stat.c
index d05a93b..c1def13 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -463,15 +463,6 @@ human_time (struct timespec t)
   return str;
 }
 
-/* Return a string representation (in static storage)
-   of the number of seconds in T since the epoch.  */
-static char * ATTRIBUTE_WARN_UNUSED_RESULT
-epoch_sec (struct timespec t)
-{
-  static char str[INT_BUFSIZE_BOUND (time_t)];
-  return timetostr (t.tv_sec, str);
-}
-
 /* Output the number of nanoseconds, ARG.tv_nsec, honoring a
    WIDTH.PRECISION format modifier, where PRECISION specifies
    how many leading digits(on a field of 9) to print.  */
@@ -491,13 +482,29 @@ out_ns (char *pformat, size_t prefix_len, struct timespec arg)
      on the default representation, i.e., a zero padded number
      of width 9.  */
   unsigned long int ns = arg.tv_nsec;
+  char *dot = memchr (pformat, '.', prefix_len);
 
-  if (memchr (pformat, '.', prefix_len)) /* precision specified.  */
+  if (dot)
     {
-      char tmp[INT_BUFSIZE_BOUND (uintmax_t)];
-      snprintf (tmp, sizeof tmp, "%09lu", ns);
-      strcpy (pformat + prefix_len, "s");
-      printf (pformat, tmp);
+      /* Precision specified.  */
+      size_t i;
+      int precision = 0;
+      for (i = dot - pformat + 1; i < prefix_len && ISDIGIT (pformat[i]); i++)
+        {
+          if (! precision)
+            precision = pformat[i] - '0';
+          else
+            {
+              /* If more than 9 digits are asked for, just output 9.  */
+              precision = 9;
+              break;
+            }
+        }
+      if (! precision)
+        return;
+      for (; precision < 9; precision++)
+        ns /= 10;
+      strcpy (dot, "lu");
     }
   else
     {
@@ -505,8 +512,9 @@ out_ns (char *pformat, size_t prefix_len, struct timespec arg)
       /* Note that pformat is big enough, as %:X -> %09lu
          and two extra bytes are already allocated.  */
       strcpy (pformat + prefix_len, fmt);
-      printf (pformat, ns);
     }
+
+  printf (pformat, ns);
 }
 
 static void
@@ -539,6 +547,14 @@ out_uint_x (char *pformat, size_t prefix_len, uintmax_t arg)
   strcpy (pformat + prefix_len, PRIxMAX);
   printf (pformat, arg);
 }
+static void
+out_epoch_sec (char *pformat, size_t prefix_len, struct timespec arg)
+{
+  if (TYPE_SIGNED (time_t))
+    out_int (pformat, prefix_len, arg.tv_sec);
+  else
+    out_uint (pformat, prefix_len, arg.tv_sec);
+}
 
 /* Print the context information of FILENAME, and return true iff the
    context could not be obtained.  */
@@ -853,8 +869,8 @@ print_stat (char *pformat, size_t prefix_len, unsigned int m,
       }
       break;
     case 'W':
-      out_string (pformat, prefix_len,
-                  epoch_sec (neg_to_zero (get_stat_birthtime (statbuf))));
+      out_epoch_sec (pformat, prefix_len,
+                     neg_to_zero (get_stat_birthtime (statbuf)));
       break;
     case 'W' + 256:
       out_ns (pformat, prefix_len, neg_to_zero (get_stat_birthtime (statbuf)));
@@ -863,7 +879,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int m,
       out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf)));
       break;
     case 'X':
-      out_string (pformat, prefix_len, epoch_sec (get_stat_atime (statbuf)));
+      out_epoch_sec (pformat, prefix_len, get_stat_atime (statbuf));
       break;
     case 'X' + 256:
       out_ns (pformat, prefix_len, get_stat_atime (statbuf));
@@ -872,7 +888,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int m,
       out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf)));
       break;
     case 'Y':
-      out_string (pformat, prefix_len, epoch_sec (get_stat_mtime (statbuf)));
+      out_epoch_sec (pformat, prefix_len, get_stat_mtime (statbuf));
       break;
     case 'Y' + 256:
       out_ns (pformat, prefix_len, get_stat_mtime (statbuf));
@@ -881,7 +897,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int m,
       out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf)));
       break;
     case 'Z':
-      out_string (pformat, prefix_len, epoch_sec (get_stat_ctime (statbuf)));
+      out_epoch_sec (pformat, prefix_len, get_stat_ctime (statbuf));
       break;
     case 'Z' + 256:
       out_ns (pformat, prefix_len, get_stat_ctime (statbuf));
-- 
1.7.2






Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Wed, 03 Nov 2010 23:39:01 GMT) Full text and rfc822 format available.

Message #20 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Eric Blake <eblake <at> redhat.com>
Cc: 7325 <at> debbugs.gnu.org, Jim Meyering <jim <at> meyering.net>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Wed, 03 Nov 2010 23:42:44 +0000
On 03/11/10 19:27, Eric Blake wrote:
> On 11/03/2010 12:59 PM, Jim Meyering wrote:
>> Note that coreutils' printf does not accept the '0' modifier in a %s format.
>>
>>     $ env printf '%05.3s\n' 23
>>     printf: %05.3s: invalid conversion specification
>>
>> That's because POSIX says the "0" modifier applies only to the
>> d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversion specifiers.
>>
>> One solution is to trim off the "0".
>> It's probably a good idea regardless, in case some implementation rejects it.
>>
>> On the other hand, I find the zero-padding you currently get
>> with stat on solaris to be slightly more intuitive.
> 
> I agree that %05.3:X resulting in 00023 would be ideal.

I disagree because I can't see how that's useful.
The above is for 023xxxxxx nanoseconds.
So what is 23 in that context?

> And I agree that we'd have to trim off the 0 modifier before calling the underlying
> printf %s, and thus be responsible for putting in '0' padding ourselves
> rather than relying on printf() padding.
> 

I'd just strip any leading 0 if a precision is specified,
to suppress the problematic solaris behavior.

cheers,
Pádraig.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 04 Nov 2010 07:29:02 GMT) Full text and rfc822 format available.

Message #23 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: 7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 04 Nov 2010 08:32:32 +0100
Pádraig Brady wrote:

> On 03/11/10 19:27, Eric Blake wrote:
>> On 11/03/2010 12:59 PM, Jim Meyering wrote:
>>> Note that coreutils' printf does not accept the '0' modifier in a %s format.
>>>
>>>     $ env printf '%05.3s\n' 23
>>>     printf: %05.3s: invalid conversion specification
>>>
>>> That's because POSIX says the "0" modifier applies only to the
>>> d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversion specifiers.
>>>
>>> One solution is to trim off the "0".
>>> It's probably a good idea regardless, in case some implementation rejects it.
>>>
>>> On the other hand, I find the zero-padding you currently get
>>> with stat on solaris to be slightly more intuitive.
>>
>> I agree that %05.3:X resulting in 00023 would be ideal.
>
> I disagree because I can't see how that's useful.
> The above is for 023xxxxxx nanoseconds.
> So what is 23 in that context?

The reason I prefer the above is that (regardless of semantics)
it is consistent with what one would expect of a numeric conversion
specifier.  That means no surprises for the user who knows about printf
and no need to document anything different about how stat's %[WXYZ]
specifiers work.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 04 Nov 2010 07:33:02 GMT) Full text and rfc822 format available.

Message #26 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 04 Nov 2010 08:37:00 +0100
Paul Eggert wrote:
> The test-case part of that looks OK, but the change to stat.c
> can be simplified.  Also, there's a similar problem with a format
> like %020X, which should be fixed too.
>
> While we're on the subject, there are other ways that stat invokers
> can exercise undefined behavior (in the C sense) by passing
> weird formats in.  This really should get fixed at some point.
> The patch proposed below addresses just the immediate issue.
>
>>From a24a9ce8f3711670a6413c60b5e9ebd3e51a4e06 Mon Sep 17 00:00:00 2001
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> Date: Wed, 3 Nov 2010 15:49:50 -0700
> Subject: [PATCH] stat: handle leading '0' when formatting secs and ns
>
> * src/stat.c (epoch_sec): Remove. All callers changed to use
> out_epoch_sec instead.
> (out_ns): Use numeric format, not string format, to output
> the nanoseconds count; this avoids unportable use of (e.g.)
> %05s in a printf format.
> (out_epoch_sec): New function.  This also uses a numeric format,
> instead of a string format, to output a number.

Thanks!  I like it.
FYI, I need slightly different tests for that,
so am amending with these:

diff --git a/tests/misc/stat-nanoseconds b/tests/misc/stat-nanoseconds
index 314f43e..44862eb 100755
--- a/tests/misc/stat-nanoseconds
+++ b/tests/misc/stat-nanoseconds
@@ -26,11 +26,11 @@ ls --full-time | grep 18:43:33.023456789 \

 test "$(stat -c      %:X k)" = 023456789  || fail=1
 test "$(stat -c     %3:X k)" = 23456789   || fail=1
-test "$(stat -c   %3.3:X k)" = 023        || fail=1
-test "$(stat -c    %.3:X k)" = 023        || fail=1
+test "$(stat -c   %3.3:X k)" = ' 23'      || fail=1
+test "$(stat -c    %.3:X k)" = 23         || fail=1
 test "$(stat -c  %03.3:X k)" = 023        || fail=1
-test "$(stat -c  %-5.3:X k)" = '023  '    || fail=1
-test "$(stat -c  %05.3:X k)" = '  023'    || fail=1
-test "$(stat -c %010.3:X k)" = '       023' || fail=1
+test "$(stat -c  %-5.3:X k)" = '23   '    || fail=1
+test "$(stat -c  %05.3:X k)" = 00023      || fail=1
+test "$(stat -c %010.3:X k)" = 0000000023 || fail=1

 Exit $fail




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 04 Nov 2010 07:53:02 GMT) Full text and rfc822 format available.

Message #29 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 04 Nov 2010 08:56:54 +0100
Paul Eggert wrote:

> The test-case part of that looks OK, but the change to stat.c
> can be simplified.  Also, there's a similar problem with a format
> like %020X, which should be fixed too.
>
> While we're on the subject, there are other ways that stat invokers
> can exercise undefined behavior (in the C sense) by passing
> weird formats in.  This really should get fixed at some point.
> The patch proposed below addresses just the immediate issue.
>
>>From a24a9ce8f3711670a6413c60b5e9ebd3e51a4e06 Mon Sep 17 00:00:00 2001
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> Date: Wed, 3 Nov 2010 15:49:50 -0700
> Subject: [PATCH] stat: handle leading '0' when formatting secs and ns
>
> * src/stat.c (epoch_sec): Remove. All callers changed to use
> out_epoch_sec instead.
> (out_ns): Use numeric format, not string format, to output
> the nanoseconds count; this avoids unportable use of (e.g.)
> %05s in a printf format.
> (out_epoch_sec): New function.  This also uses a numeric format,
> instead of a string format, to output a number.

However, what about Eric's example?

  $ src/stat-p -c '_%-0 010.4:X_' k  # yours
  _234       _
  $ src/stat-j -c '_%-0 010.4:X_' k  # mine
  _0234      _

and printf (note how it includes the leading space):

  $ env printf '_%-0 010.4d_\n' 234
  _ 0234     _




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 04 Nov 2010 20:06:02 GMT) Full text and rfc822 format available.

Message #32 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Jim Meyering <jim <at> meyering.net>
Cc: 7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 04 Nov 2010 13:10:04 -0700
On 11/04/10 00:56, Jim Meyering wrote:

> However, what about Eric's example?
> 
>   $ src/stat-p -c '_%-0 010.4:X_' k  # yours
>   _234       _
>   $ src/stat-j -c '_%-0 010.4:X_' k  # mine
>   _0234      _

That's simply an issue of whether the value is considered to be signed
or unsigned, and can be fixed by the patch at the end of this message.

However, let me take a step back a minute.  Do users really want all
this functionality?  Personally, what I'd like to see is a single
format like this:

   %.3X

that prints out the entire seconds since the Epoch, truncated
to millseconds.  That's simpler than what we require now:

   %X.%.3:X

The changelogs suggest that we used to do things the simpler way,
but changed on Oct. 21.  I don't recall this being discussed: I 
assume it was due to floating point rounding issues.  Still, I'd
prefer the simpler notation, and we should be able to implement it
without floating point.  Would that be OK?  The idea would be
to support ".PRECISION" in the formats for W, X, Y, and Z, and
to drop support for ':W' and the like.

From 1dc473cc61099d5a1bf6bc26358bafd81cd670bd Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert <at> cs.ucla.edu>
Date: Thu, 4 Nov 2010 12:56:17 -0700
Subject: [PATCH] * src/stat.c (out_ns): Treat the ns value as being signed.

---
 src/stat.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/stat.c b/src/stat.c
index c1def13..dd352a4 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -481,7 +481,7 @@ out_ns (char *pformat, size_t prefix_len, struct timespec arg)
      in the modifier, then then treat the modifier as operating
      on the default representation, i.e., a zero padded number
      of width 9.  */
-  unsigned long int ns = arg.tv_nsec;
+  long int ns = arg.tv_nsec;
   char *dot = memchr (pformat, '.', prefix_len);
 
   if (dot)
@@ -504,12 +504,12 @@ out_ns (char *pformat, size_t prefix_len, struct timespec arg)
         return;
       for (; precision < 9; precision++)
         ns /= 10;
-      strcpy (dot, "lu");
+      strcpy (dot, "ld");
     }
   else
     {
-      char const *fmt = (prefix_len == 1) ? "09lu" : "lu";
-      /* Note that pformat is big enough, as %:X -> %09lu
+      char const *fmt = (prefix_len == 1) ? "09ld" : "ld";
+      /* Note that pformat is big enough, as %:X -> %09ld
          and two extra bytes are already allocated.  */
       strcpy (pformat + prefix_len, fmt);
     }
-- 
1.7.2





Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 04 Nov 2010 20:39:01 GMT) Full text and rfc822 format available.

Message #35 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 04 Nov 2010 21:42:29 +0100
Paul Eggert wrote:
> On 11/04/10 00:56, Jim Meyering wrote:
>
>> However, what about Eric's example?
>>
>>   $ src/stat-p -c '_%-0 010.4:X_' k  # yours
>>   _234       _
>>   $ src/stat-j -c '_%-0 010.4:X_' k  # mine
>>   _0234      _
>
> That's simply an issue of whether the value is considered to be signed
> or unsigned, and can be fixed by the patch at the end of this message.
>
> However, let me take a step back a minute.  Do users really want all
> this functionality?  Personally, what I'd like to see is a single
> format like this:
>
>    %.3X
>
> that prints out the entire seconds since the Epoch, truncated
> to millseconds.  That's simpler than what we require now:
>
>    %X.%.3:X
>
> The changelogs suggest that we used to do things the simpler way,
> but changed on Oct. 21.  I don't recall this being discussed: I

It was due to portability concerns, since with coreutils-8.6,
%X, %Y, etc. expanded to floating point values, and that broke
backwards compatibility:

  http://thread.gmane.org/gmane.comp.gnu.coreutils.general/161/focus=366

However, enabling floating point output only when there is a ".PREC"
part of the format sounds like a fine compromise.
Sure, old scripts that used %.3X (expecting no ".") would break,
but I doubt any such uses exist, since that notation did nothing useful.

A patch would be most welcome.


> assume it was due to floating point rounding issues.  Still, I'd
> prefer the simpler notation, and we should be able to implement it
> without floating point.  Would that be OK?  The idea would be
> to support ".PRECISION" in the formats for W, X, Y, and Z, and
> to drop support for ':W' and the like.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Fri, 05 Nov 2010 01:02:02 GMT) Full text and rfc822 format available.

Message #38 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>,
	Jim Meyering <jim <at> meyering.net>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Fri, 05 Nov 2010 01:05:32 +0000
On 04/11/10 20:10, Paul Eggert wrote:
> On 11/04/10 00:56, Jim Meyering wrote:
> 
>> However, what about Eric's example?
>>
>>   $ src/stat-p -c '_%-0 010.4:X_' k  # yours
>>   _234       _
>>   $ src/stat-j -c '_%-0 010.4:X_' k  # mine
>>   _0234      _
> 
> That's simply an issue of whether the value is considered to be signed
> or unsigned, and can be fixed by the patch at the end of this message.
> 
> However, let me take a step back a minute.  Do users really want all
> this functionality?  Personally, what I'd like to see is a single
> format like this:
> 
>    %.3X
> 
> that prints out the entire seconds since the Epoch, truncated
> to millseconds.  That's simpler than what we require now:
> 
>    %X.%.3:X
> 
> The changelogs suggest that we used to do things the simpler way,
> but changed on Oct. 21.  I don't recall this being discussed: I 
> assume it was due to floating point rounding issues.  Still, I'd
> prefer the simpler notation, and we should be able to implement it
> without floating point.  Would that be OK?  The idea would be
> to support ".PRECISION" in the formats for W, X, Y, and Z, and
> to drop support for ':W' and the like.

I think you're echoing my suggestion here:
http://comments.gmane.org/gmane.comp.gnu.coreutils.general/369
Given the counter arguments there it was decided to
split to X and :X etc.

I still slightly prefer just using %.X as
it's backwards compat with older coreutils (excluding 8.6).

cheers,
Pádraig.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Fri, 05 Nov 2010 06:30:03 GMT) Full text and rfc822 format available.

Message #41 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: Eric Blake <eblake <at> redhat.com>, Paul Eggert <eggert <at> cs.ucla.edu>,
	7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Fri, 05 Nov 2010 07:34:25 +0100
Pádraig Brady wrote:
...
>> That's simply an issue of whether the value is considered to be signed
>> or unsigned, and can be fixed by the patch at the end of this message.
>>
>> However, let me take a step back a minute.  Do users really want all
>> this functionality?  Personally, what I'd like to see is a single
>> format like this:
>>
>>    %.3X
>>
>> that prints out the entire seconds since the Epoch, truncated
>> to millseconds.  That's simpler than what we require now:
>>
>>    %X.%.3:X
>>
>> The changelogs suggest that we used to do things the simpler way,
>> but changed on Oct. 21.  I don't recall this being discussed: I
>> assume it was due to floating point rounding issues.  Still, I'd
>> prefer the simpler notation, and we should be able to implement it
>> without floating point.  Would that be OK?  The idea would be
>> to support ".PRECISION" in the formats for W, X, Y, and Z, and
>> to drop support for ':W' and the like.
>
> I think you're echoing my suggestion here:
> http://comments.gmane.org/gmane.comp.gnu.coreutils.general/369

Oh!  Indeed.
Sorry I didn't see that part of the thread.

> Given the counter arguments there it was decided to
> split to X and :X etc.
>
> I still slightly prefer just using %.X as
> it's backwards compat with older coreutils (excluding 8.6).

So do I.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Fri, 05 Nov 2010 18:30:02 GMT) Full text and rfc822 format available.

Message #44 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Fri, 05 Nov 2010 19:34:07 +0100
Jim Meyering wrote:
> Paul Eggert wrote:
>> On 11/04/10 00:56, Jim Meyering wrote:
>>
>>> However, what about Eric's example?
>>>
>>>   $ src/stat-p -c '_%-0 010.4:X_' k  # yours
>>>   _234       _
>>>   $ src/stat-j -c '_%-0 010.4:X_' k  # mine
>>>   _0234      _
>>
>> That's simply an issue of whether the value is considered to be signed
>> or unsigned, and can be fixed by the patch at the end of this message.
>>
>> However, let me take a step back a minute.  Do users really want all
>> this functionality?  Personally, what I'd like to see is a single
>> format like this:
>>
>>    %.3X
>>
>> that prints out the entire seconds since the Epoch, truncated
>> to millseconds.  That's simpler than what we require now:
>>
>>    %X.%.3:X
>>
>> The changelogs suggest that we used to do things the simpler way,
>> but changed on Oct. 21.  I don't recall this being discussed: I
>
> It was due to portability concerns, since with coreutils-8.6,
> %X, %Y, etc. expanded to floating point values, and that broke
> backwards compatibility:
>
>   http://thread.gmane.org/gmane.comp.gnu.coreutils.general/161/focus=366
>
> However, enabling floating point output only when there is a ".PREC"
> part of the format sounds like a fine compromise.
> Sure, old scripts that used %.3X (expecting no ".") would break,
> but I doubt any such uses exist, since that notation did nothing useful.
>
> A patch would be most welcome.

Hi Paul,
Please let us know whether you are working on this.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Sat, 06 Nov 2010 02:27:02 GMT) Full text and rfc822 format available.

Message #47 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Jim Meyering <jim <at> meyering.net>
Cc: 7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Fri, 05 Nov 2010 19:31:03 -0700
On 11/05/2010 11:34 AM, Jim Meyering wrote:

> Please let us know whether you are working on this.

Yes I am.  (So hard that I wasn't reading my email.  :-)
Please expect a patch soon, but it won't be tiny.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Sat, 06 Nov 2010 02:51:01 GMT) Full text and rfc822 format available.

Message #50 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Jim Meyering <jim <at> meyering.net>
Cc: Eric Blake <eblake <at> redhat.com>, 7325 <at> debbugs.gnu.org,
	Pádraig Brady <P <at> draigBrady.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Fri, 05 Nov 2010 19:54:28 -0700
On 11/04/2010 11:34 PM, Jim Meyering wrote:
> Pádraig Brady wrote:
>> I still slightly prefer just using %.X as
>> it's backwards compat with older coreutils (excluding 8.6).
> 
> So do I.

I built that and tried it out, and found another problem that has been
annoying me for years in other programs: 'stat' prints out unnecessary
trailing zeros for time stamps, when the file system resolution is
coarser than nanosecond resolution.  So I figured I'd fix that too,
for 'stat' (other programs can be fixed later).  With this fix, %.X
outputs the time stamp but omits trailing zeros if it can infer that
the file system would always put zeros there.  If you want a specific
number of zeros, you can use something like %.3X or %.9X (or %.100X :-).

From d37bad3d644a98887402b5398b7280701a7b7559 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert <at> cs.ucla.edu>
Date: Fri, 5 Nov 2010 19:35:12 -0700
Subject: [PATCH] stat: use e.g. %.3X instead of %X.%3:X for sub-second precision

* NEWS: Document this.
* doc/coreutils.texi (stat invocation): Likewise.
* gl/lib/fstimeprec.c, gl/lib/fstimeprec.h, gl/modules/fstimeprec:
* gl/modules/fstimeprec-tests, gl/tests/test-fstimeprec.c:
New files.
* bootstrap.conf (gnulib_modules): Add fstimeprec.
* src/stat.c: Include fstimeprec.h.  Don't include xstrtol.h.
(decimal_point, decimal_point_len): New static vars.
(main): Initialize them.
(epoch_sec, out_ns): Remove.
(out_int, out_uint): Now returns whatever printf returned.
(out_minus_zero, out_epoch_secs): New functions.
(print_stat): Use out_epoch_sec instead of out_ns and epoch_sec.
(print_stat, print_it, usage): Remove the %:X-style formats.
* tests/misc/stat-nanoseconds: Set TZ=UTC0 to avoid problems
with weird time zones.  Use a time stamp near the Epoch so that we
don't have to worry about leap seconds.  Redo test cases to match
new behavior.
* tests/touch/60-seconds: Change %Y.%:Y to %.9Y, to adjust to
new behavior.
---
 NEWS                        |   10 +--
 bootstrap.conf              |    1 +
 doc/coreutils.texi          |   37 ++++----
 gl/lib/fstimeprec.c         |  178 +++++++++++++++++++++++++++++++++++
 gl/lib/fstimeprec.h         |   22 +++++
 gl/modules/fstimeprec       |   24 +++++
 gl/modules/fstimeprec-tests |   10 ++
 gl/tests/test-fstimeprec.c  |   74 +++++++++++++++
 src/stat.c                  |  218 ++++++++++++++++++++++++++-----------------
 tests/misc/stat-nanoseconds |   25 +++--
 tests/touch/60-seconds      |    2 +-
 11 files changed, 480 insertions(+), 121 deletions(-)
 create mode 100644 gl/lib/fstimeprec.c
 create mode 100644 gl/lib/fstimeprec.h
 create mode 100644 gl/modules/fstimeprec
 create mode 100644 gl/modules/fstimeprec-tests
 create mode 100644 gl/tests/test-fstimeprec.c

diff --git a/NEWS b/NEWS
index 3b9bea2..1e5a8db 100644
--- a/NEWS
+++ b/NEWS
@@ -20,16 +20,12 @@ GNU coreutils NEWS                                    -*- outline -*-
   stat's %X, %Y, and %Z directives once again print only the integer
   part of seconds since the epoch.  This reverts a change from
   coreutils-8.6, that was deemed unnecessarily disruptive.  To obtain
-  the nanoseconds portion corresponding to %X, you may now use %:X.
-  I.e., to print the floating point number of seconds using maximum
-  precision, use this format string: %X.%:X.  Likewise for %Y, %Z and %W.
+  a full resolution time stamp for %X, use %.X; if you want (say) just
+  3 fractional digits, use %.3X.  Likewise for %Y and %Z.
 
   stat's new %W format directive would print floating point seconds.
   However, with the above change to %X, %Y and %Z, we've made %W work
-  the same way:  %W now expands to seconds since the epoch (or 0 when
-  not supported), and %:W expands to the nanoseconds portion, or to
-  0 if not supported.
-
+  the same way as the others.
 
 * Noteworthy changes in release 8.6 (2010-10-15) [stable]
 
diff --git a/bootstrap.conf b/bootstrap.conf
index 18ef914..5a6ebae 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -85,6 +85,7 @@ gnulib_modules="
   freopen
   freopen-safer
   fseeko
+  fstimeprec
   fsusage
   fsync
   ftello
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index be5999f..8dfb069 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -10707,37 +10707,36 @@ The valid @var{format} directives for files with @option{--format} and
 @item %U - User name of owner
 @item %w - Time of file birth, or @samp{-} if unknown
 @item %W - Time of file birth as seconds since Epoch, or @samp{0}
-@item %:W - Time of file birth: nanoseconds remainder, or @samp{0}
 @item %x - Time of last access
 @item %X - Time of last access as seconds since Epoch
-@item %:X - Time of last access: nanoseconds remainder
 @item %y - Time of last modification
 @item %Y - Time of last modification as seconds since Epoch
-@item %:Y - Time of last modification: nanoseconds remainder
 @item %z - Time of last change
 @item %Z - Time of last change as seconds since Epoch
-@item %:Z - Time of last change: nanoseconds remainder
 @end itemize
 
-Note that each of @samp{%:W}, @samp{%:X}, @samp{%:Y} and @samp{%:Z}
-prints its zero-padded number of nanoseconds on a field of width 9.
-However, if you specify anything between the @samp{%} and @samp{:},
-e.g., @samp{%10:X}, your modifier replaces the default of @samp{09}.
-
-Here are some examples:
+The @samp{%W}, @samp{%X}, @samp{%Y}, and @samp{%Z} formats accept a
+precision preceded by a period to specify the number of digits to
+print after the decimal point. For example, @samp{%.9X} outputs the
+last access time to nanosecond precision.  If a period is given but no
+precision, @command{stat} uses the estimated precision of the file
+system. When discarding excess precision, time stamps are truncated
+toward minus infinity.
 
 @example
 zero pad:
-  $ stat -c '[%015:Y]' /usr
-  [000000031367045]
+  $ stat -c '[%015Y]' /usr
+  [000001288929712]
 space align:
-  $ stat -c '[%15:Y]' /usr
-  [       31367045]
-  $ stat -c '[%-15:Y]' /usr
-  [31367045       ]
-truncate:
-  $ stat -c '[%.3:Y]' /usr
-  [031]
+  $ stat -c '[%15Y]' /usr
+  [     1288929712]
+  $ stat -c '[%-15Y]' /usr
+  [1288929712     ]
+precision:
+  $ stat -c '[%.3Y]' /usr
+  [1288929712.114]
+  $ stat -c '[%.Y]' /usr
+  [1288929712.114951]
 @end example
 
 The mount point printed by @samp{%m} is similar to that output
diff --git a/gl/lib/fstimeprec.c b/gl/lib/fstimeprec.c
new file mode 100644
index 0000000..fd63054
--- /dev/null
+++ b/gl/lib/fstimeprec.c
@@ -0,0 +1,178 @@
+/* Determine a file system's time stamp precision.
+
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+#include "fstimeprec.h"
+
+#include "hash.h"
+#include "stat-time.h"
+#include <limits.h>
+#include <stdlib.h>
+
+/* A hash table that maps device numbers to precisions.  */
+struct fstimeprec
+{
+  /* Map device numbers to precisions.  */
+  struct hash_table *map;
+
+  /* Cache of the most recently allocated and otherwise-unused storage
+     for probing this table.  */
+  struct ent *probe;
+};
+
+/* A pair that maps a device number to a precision.  */
+struct ent
+{
+  dev_t dev;
+  int prec;
+};
+
+/* Hash an entry.  */
+static size_t
+ent_hash (void const *x, size_t table_size)
+{
+  struct ent const *p = x;
+  dev_t dev = p->dev;
+
+  /* FIXME: This code is duplicated from di-set.c.  */
+  /* When DEV is wider than size_t, exclusive-OR the words of DEV into H.
+     This avoids loss of info, without applying % to the wider type,
+     which could be quite slow on some systems.  */
+  size_t h = dev;
+  unsigned int i;
+  unsigned int n_words = sizeof dev / sizeof h + (sizeof dev % sizeof h != 0);
+  for (i = 1; i < n_words; i++)
+    h ^= dev >> CHAR_BIT * sizeof h * i;
+
+  return h % table_size;
+}
+
+/* Return true if two entries are the same.  */
+static bool
+ent_compare (void const *x, void const *y)
+{
+  struct ent const *a = x;
+  struct ent const *b = y;
+  return a->dev == b->dev;
+}
+
+/* Using the SET table, map a device to an entry that represents
+   the file system precision.  Return NULL on error.  */
+static struct ent *
+map_device (struct fstimeprec *tab, dev_t dev)
+{
+  /* Find space for the probe, reusing the cache if available.  */
+  struct ent *ent;
+  struct ent *probe = tab->probe;
+  if (probe)
+    {
+      /* If repeating a recent query, return the cached result.   */
+      if (probe->dev == dev)
+        return probe;
+    }
+  else
+    {
+      tab->probe = probe = malloc (sizeof *probe);
+      if (! probe)
+        return NULL;
+      probe->prec = 0;
+    }
+
+  /* Probe for the device.  */
+  probe->dev = dev;
+  ent = hash_insert (tab->map, probe);
+  if (ent == probe)
+    tab->probe = NULL;
+  return ent;
+}
+
+/* Return a newly allocated table of file system time stamp
+   resolutions, or NULL if out of memory.  */
+struct fstimeprec *
+fstimeprec_alloc (void)
+{
+  struct fstimeprec *tab = malloc (sizeof *tab);
+  if (tab)
+    {
+      enum { INITIAL_DEV_MAP_SIZE = 11 };
+      tab->map = hash_initialize (INITIAL_DEV_MAP_SIZE, NULL,
+                                  ent_hash, ent_compare, free);
+      if (! tab->map)
+        {
+          free (tab);
+          return NULL;
+        }
+      tab->probe = NULL;
+    }
+  return tab;
+}
+
+/* Free TAB.  */
+void
+fstimeprec_free (struct fstimeprec *tab)
+{
+  hash_free (tab->map);
+  free (tab->probe);
+  free (tab);
+}
+
+/* Using the cached information in TAB, return the estimated precision
+   of time stamps for the file system containing the file whose status
+   info is in ST.  The returned value counts the number of decimal
+   fraction digits.  Return 0 on failure.
+
+   If TAB is null, the guess is based purely on ST.  */
+int
+fstimeprec (struct fstimeprec *tab, struct stat const *st)
+{
+  /* Map the device number to an entry.  */
+  struct ent *ent = (tab ? map_device (tab, st->st_dev) : NULL);
+
+  /* Guess the precision based on what has been seen so far.  */
+  int prec = (ent ? ent->prec : 0);
+
+  /* If the current file's timestamp resolution is higher than the
+     guess, increase the guess.  */
+  if (prec < 9)
+    {
+      struct timespec ats = get_stat_atime (st);
+      struct timespec mts = get_stat_mtime (st);
+      struct timespec cts = get_stat_ctime (st);
+      struct timespec bts = get_stat_birthtime (st);
+      unsigned int ans = ats.tv_nsec;
+      unsigned int mns = mts.tv_nsec;
+      unsigned int cns = cts.tv_nsec;
+      unsigned int bns = bts.tv_nsec < 0 ? 0 : bts.tv_nsec;
+      unsigned int power = 10;
+      int p;
+      for (p = prec + 1; p < 9; p++)
+        power *= 10;
+
+      while (ans % power | mns % power | cns % power | bns % power)
+        {
+          power /= 10;
+          prec++;
+        }
+
+      if (ent)
+        ent->prec = prec;
+    }
+
+  return prec;
+}
diff --git a/gl/lib/fstimeprec.h b/gl/lib/fstimeprec.h
new file mode 100644
index 0000000..8ec24df
--- /dev/null
+++ b/gl/lib/fstimeprec.h
@@ -0,0 +1,22 @@
+#include <sys/stat.h>
+
+#ifndef ATTRIBUTE_MALLOC
+# if __GNUC__ >= 3
+#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+#  define ATTRIBUTE_MALLOC
+# endif
+#endif
+
+#ifndef _GL_ARG_NONNULL
+# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3
+#  define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params))
+# else
+#  define _GL_ARG_NONNULL(params)
+# endif
+#endif
+
+struct fstimeprec *fstimeprec_alloc (void) ATTRIBUTE_MALLOC;
+void fstimeprec_free (struct fstimeprec *) _GL_ARG_NONNULL ((1));
+int fstimeprec (struct fstimeprec *, struct stat const *)
+  _GL_ARG_NONNULL ((2));
diff --git a/gl/modules/fstimeprec b/gl/modules/fstimeprec
new file mode 100644
index 0000000..787c2e7
--- /dev/null
+++ b/gl/modules/fstimeprec
@@ -0,0 +1,24 @@
+Description:
+estimate precision of time stamps in file systems
+
+Files:
+lib/fstimeprec.c
+lib/fstimeprec.h
+
+Depends-on:
+hash
+stat-time
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += fstimeprec.c fstimeprec.h
+
+Include:
+"fstimeprec.h"
+
+License
+GPL
+
+Maintainer:
+Paul Eggert and Jim Meyering
diff --git a/gl/modules/fstimeprec-tests b/gl/modules/fstimeprec-tests
new file mode 100644
index 0000000..bf6b49e
--- /dev/null
+++ b/gl/modules/fstimeprec-tests
@@ -0,0 +1,10 @@
+Files:
+tests/test-fstimeprec.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-fstimeprec
+check_PROGRAMS += test-fstimeprec
diff --git a/gl/tests/test-fstimeprec.c b/gl/tests/test-fstimeprec.c
new file mode 100644
index 0000000..f699139
--- /dev/null
+++ b/gl/tests/test-fstimeprec.c
@@ -0,0 +1,74 @@
+/* Test the fstimeprec module.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+#define ASSERT(expr) \
+  do                                                                         \
+    {                                                                        \
+      if (!(expr))                                                           \
+        {                                                                    \
+          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+          fflush (stderr);                                                   \
+          abort ();                                                          \
+        }                                                                    \
+    }                                                                        \
+  while (0)
+
+#include "fstimeprec.h"
+
+static int
+fstimeprec_file (struct fstimeprec *tab, char const *file)
+{
+  struct stat st;
+  if (stat (file, &st) != 0)
+    return 0;
+  return fstimeprec (tab, &st);
+}
+
+int
+main (void)
+{
+  struct fstimeprec *tab = fstimeprec_alloc ();
+  ASSERT (tab);
+
+  int m1 = fstimeprec_file (tab, "/");
+  int m2 = fstimeprec_file (tab, ".");
+  int m3 = fstimeprec_file (tab, "..");
+  ASSERT (0 <= m1 && m1 <= 9);
+  ASSERT (0 <= m2 && m2 <= 9);
+  ASSERT (0 <= m3 && m3 <= 9);
+
+  int n1 = fstimeprec_file (tab, "/");
+  int n2 = fstimeprec_file (tab, ".");
+  int n3 = fstimeprec_file (tab, "..");
+  ASSERT (0 <= n1 && n1 <= 9);
+  ASSERT (0 <= n2 && n2 <= 9);
+  ASSERT (0 <= n3 && n3 <= 9);
+
+  ASSERT (m1 <= n1);
+  ASSERT (m2 <= n2);
+  ASSERT (m3 <= n3);
+
+  fstimeprec_free (tab);
+
+  return 0;
+}
diff --git a/src/stat.c b/src/stat.c
index d05a93b..cbf6d25 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -63,6 +63,7 @@
 #include "file-type.h"
 #include "filemode.h"
 #include "fs.h"
+#include "fstimeprec.h"
 #include "getopt.h"
 #include "mountlist.h"
 #include "quote.h"
@@ -70,7 +71,6 @@
 #include "stat-time.h"
 #include "strftime.h"
 #include "find-mount-point.h"
-#include "xstrtol.h"
 #include "xvasprintf.h"
 
 #if USE_STATVFS
@@ -183,6 +183,10 @@ static bool interpret_backslash_escapes;
    "" for --printf=FMT, "\n" for --format=FMT (-c).  */
 static char const *trailing_delim = "";
 
+/* The representation of the decimal point in the current locale.  */
+static char const *decimal_point;
+static size_t decimal_point_len;
+
 /* 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).
@@ -463,69 +467,23 @@ human_time (struct timespec t)
   return str;
 }
 
-/* Return a string representation (in static storage)
-   of the number of seconds in T since the epoch.  */
-static char * ATTRIBUTE_WARN_UNUSED_RESULT
-epoch_sec (struct timespec t)
-{
-  static char str[INT_BUFSIZE_BOUND (time_t)];
-  return timetostr (t.tv_sec, str);
-}
-
-/* Output the number of nanoseconds, ARG.tv_nsec, honoring a
-   WIDTH.PRECISION format modifier, where PRECISION specifies
-   how many leading digits(on a field of 9) to print.  */
-static void
-out_ns (char *pformat, size_t prefix_len, struct timespec arg)
-{
-  /* If no format modifier is specified, i.e., nothing between the
-     "%" and ":" of "%:X", then use the default of zero-padding and
-     a width of 9.  Otherwise, use the specified modifier(s).
-     This is to avoid the mistake of omitting the zero padding on
-     a number with fewer digits than the field width: when printing
-     nanoseconds after a decimal place, the resulting floating point
-     fraction would be off by a factor of 10 or more.
-
-     If a precision/max width is specified, i.e., a '.' is present
-     in the modifier, then then treat the modifier as operating
-     on the default representation, i.e., a zero padded number
-     of width 9.  */
-  unsigned long int ns = arg.tv_nsec;
-
-  if (memchr (pformat, '.', prefix_len)) /* precision specified.  */
-    {
-      char tmp[INT_BUFSIZE_BOUND (uintmax_t)];
-      snprintf (tmp, sizeof tmp, "%09lu", ns);
-      strcpy (pformat + prefix_len, "s");
-      printf (pformat, tmp);
-    }
-  else
-    {
-      char const *fmt = (prefix_len == 1) ? "09lu" : "lu";
-      /* Note that pformat is big enough, as %:X -> %09lu
-         and two extra bytes are already allocated.  */
-      strcpy (pformat + prefix_len, fmt);
-      printf (pformat, ns);
-    }
-}
-
 static void
 out_string (char *pformat, size_t prefix_len, char const *arg)
 {
   strcpy (pformat + prefix_len, "s");
   printf (pformat, arg);
 }
-static void
+static int
 out_int (char *pformat, size_t prefix_len, intmax_t arg)
 {
   strcpy (pformat + prefix_len, PRIdMAX);
-  printf (pformat, arg);
+  return printf (pformat, arg);
 }
-static void
+static int
 out_uint (char *pformat, size_t prefix_len, uintmax_t arg)
 {
   strcpy (pformat + prefix_len, PRIuMAX);
-  printf (pformat, arg);
+  return printf (pformat, arg);
 }
 static void
 out_uint_o (char *pformat, size_t prefix_len, uintmax_t arg)
@@ -539,6 +497,120 @@ out_uint_x (char *pformat, size_t prefix_len, uintmax_t arg)
   strcpy (pformat + prefix_len, PRIxMAX);
   printf (pformat, arg);
 }
+static int
+out_minus_zero (char *pformat, size_t prefix_len)
+{
+  strcpy (pformat + prefix_len, ".0f");
+  return printf (pformat, -0.25);
+}
+
+/* Output the number of seconds since the Epoch, using a format that
+   acts like printf's %f format.  */
+static void
+out_epoch_sec (char *pformat, size_t prefix_len, struct stat const *statbuf,
+               struct timespec arg)
+{
+  char *dot = memchr (pformat, '.', prefix_len);
+  size_t sec_prefix_len = prefix_len;
+  int width = 0;
+  int precision = 0;
+  bool frac_left_adjust = false;
+
+  if (dot)
+    {
+      sec_prefix_len = dot - pformat;
+      pformat[prefix_len] = '\0';
+
+      if (ISDIGIT (dot[1]))
+        {
+          long int lprec = strtol (dot + 1, NULL, 10);
+          precision = (lprec <= INT_MAX ? lprec : INT_MAX);
+        }
+      else
+        {
+          static struct fstimeprec *tab;
+          if (! tab)
+            tab = fstimeprec_alloc ();
+          precision = fstimeprec (tab, statbuf);
+        }
+
+      if (precision && ISDIGIT (dot[-1]))
+        {
+          /* If a nontrivial width is given, subtract the width of the
+             decimal point and PRECISION digits that will be output
+             later.  */
+          char *p = dot;
+          *dot = '\0';
+
+          do
+            --p;
+          while (ISDIGIT (p[-1]));
+
+          long int lwidth = strtol (p, NULL, 10);
+          width = (lwidth <= INT_MAX ? lwidth : INT_MAX);
+          if (1 < width)
+            {
+              p += (*p == '0');
+              sec_prefix_len = p - pformat;
+              int w_d = (decimal_point_len < width
+                         ? width - decimal_point_len
+                         : 0);
+              if (1 < w_d)
+                {
+                  int w = w_d - precision;
+                  if (1 < w)
+                    {
+                      char *dst = pformat;
+                      for (char const *src = dst; src < p; src++)
+                        if (*src == '-')
+                          frac_left_adjust = true;
+                        else
+                          *dst++ = *src;
+                      sec_prefix_len =
+                        (dst - pformat
+                         + (frac_left_adjust ? 0 : sprintf (dst, "%d", w)));
+                    }
+                }
+            }
+        }
+    }
+
+  int divisor = 1;
+  for (int i = precision; i < 9; i++)
+    divisor *= 10;
+  int frac_sec = arg.tv_nsec / divisor;
+  int int_len;
+
+  if (TYPE_SIGNED (time_t))
+    {
+      bool minus_zero = false;
+      if (arg.tv_sec < 0 && arg.tv_nsec != 0)
+        {
+          int frac_sec_modulus = 1000000000 / divisor;
+          frac_sec = (frac_sec_modulus - frac_sec
+                      - (arg.tv_nsec % divisor != 0));
+          arg.tv_sec += (frac_sec != 0);
+          minus_zero = (arg.tv_sec == 0);
+        }
+      int_len = (minus_zero
+                 ? out_minus_zero (pformat, sec_prefix_len)
+                 : out_int (pformat, sec_prefix_len, arg.tv_sec));
+    }
+  else
+    int_len = out_uint (pformat, sec_prefix_len, arg.tv_sec);
+
+  if (precision)
+    {
+      int prec = (precision < 9 ? precision : 9);
+      int trailing_prec = precision - prec;
+      int ilen = (int_len < 0 ? 0 : int_len);
+      int trailing_width = (ilen < width && decimal_point_len < width - ilen
+                            ? width - ilen - decimal_point_len - prec
+                            : 0);
+      printf ("%s%.*d%-*.*d", decimal_point, prec, frac_sec,
+              trailing_width, trailing_prec, 0);
+    }
+}
 
 /* Print the context information of FILENAME, and return true iff the
    context could not be obtained.  */
@@ -853,38 +925,26 @@ print_stat (char *pformat, size_t prefix_len, unsigned int m,
       }
       break;
     case 'W':
-      out_string (pformat, prefix_len,
-                  epoch_sec (neg_to_zero (get_stat_birthtime (statbuf))));
-      break;
-    case 'W' + 256:
-      out_ns (pformat, prefix_len, neg_to_zero (get_stat_birthtime (statbuf)));
+      out_epoch_sec (pformat, prefix_len, statbuf,
+                     neg_to_zero (get_stat_birthtime (statbuf)));
       break;
     case 'x':
       out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf)));
       break;
     case 'X':
-      out_string (pformat, prefix_len, epoch_sec (get_stat_atime (statbuf)));
-      break;
-    case 'X' + 256:
-      out_ns (pformat, prefix_len, get_stat_atime (statbuf));
+      out_epoch_sec (pformat, prefix_len, statbuf, 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_sec (get_stat_mtime (statbuf)));
-      break;
-    case 'Y' + 256:
-      out_ns (pformat, prefix_len, get_stat_mtime (statbuf));
+      out_epoch_sec (pformat, prefix_len, statbuf, 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_sec (get_stat_ctime (statbuf)));
-      break;
-    case 'Z' + 256:
-      out_ns (pformat, prefix_len, get_stat_ctime (statbuf));
+      out_epoch_sec (pformat, prefix_len, statbuf, get_stat_ctime (statbuf));
       break;
     case 'C':
       fail |= out_file_context (pformat, prefix_len, filename);
@@ -968,21 +1028,9 @@ 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;
+            unsigned int fmt_code = *fmt_char;
             memcpy (dest, b, len + 1);
 
-            /* The ":" modifier just before the letter in %W, %X, %Y, %Z
-               tells stat to print the nanoseconds portion of the date.  */
-            if (*fmt_char == ':' && strchr ("WXYZ", fmt_char[1]))
-              {
-                fmt_code = fmt_char[1] + 256;
-                ++fmt_char;
-              }
-            else
-              {
-                fmt_code = fmt_char[0];
-              }
-
             b = fmt_char;
             switch (fmt_code)
               {
@@ -1276,16 +1324,12 @@ The valid format sequences for files (without --file-system):\n\
   %U   User name of owner\n\
   %w   Time of file birth, human-readable; - if unknown\n\
   %W   Time of file birth, seconds since Epoch; 0 if unknown\n\
-  %:W  Time of file birth, nanoseconds remainder; 0 if unknown\n\
   %x   Time of last access, human-readable\n\
   %X   Time of last access, seconds since Epoch\n\
-  %:X  Time of last access, nanoseconds remainder\n\
   %y   Time of last modification, human-readable\n\
   %Y   Time of last modification, seconds since Epoch\n\
-  %:Y  Time of last modification, nanoseconds remainder\n\
   %z   Time of last change, human-readable\n\
   %Z   Time of last change, seconds since Epoch\n\
-  %:Z  Time of last change, nanoseconds remainder\n\
 \n\
 "), stdout);
 
@@ -1330,6 +1374,10 @@ main (int argc, char *argv[])
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
 
+  struct lconv const *locale = localeconv ();
+  decimal_point = (locale->decimal_point[0] ? locale->decimal_point : ".");
+  decimal_point_len = strlen (decimal_point);
+
   atexit (close_stdout);
 
   while ((c = getopt_long (argc, argv, "c:fLt", long_options, NULL)) != -1)
diff --git a/tests/misc/stat-nanoseconds b/tests/misc/stat-nanoseconds
index 314f43e..9071ae9 100755
--- a/tests/misc/stat-nanoseconds
+++ b/tests/misc/stat-nanoseconds
@@ -19,18 +19,25 @@
 test "$VERBOSE" = yes && stat --version
 . "${srcdir=.}/init.sh"; path_prepend_ ../src
 
-touch -d '2010-10-21 18:43:33.023456789' k || framework_failure_
+TZ=UTC0
+export TZ
+
+touch -d '1970-01-01 18:43:33.023456789' k || framework_failure_
 
 ls --full-time | grep 18:43:33.023456789 \
   || skip_ this file system does not support sub-second time stamps
 
-test "$(stat -c      %:X k)" = 023456789  || fail=1
-test "$(stat -c     %3:X k)" = 23456789   || fail=1
-test "$(stat -c   %3.3:X k)" = 023        || fail=1
-test "$(stat -c    %.3:X k)" = 023        || fail=1
-test "$(stat -c  %03.3:X k)" = 023        || fail=1
-test "$(stat -c  %-5.3:X k)" = '023  '    || fail=1
-test "$(stat -c  %05.3:X k)" = '  023'    || fail=1
-test "$(stat -c %010.3:X k)" = '       023' || fail=1
+test "$(stat -c       %X k)" =    67413               || fail=1
+test "$(stat -c      %.X k)" =    67413.023456789     || fail=1
+test "$(stat -c     %.1X k)" =    67413.0             || fail=1
+test "$(stat -c     %.3X k)" =    67413.023           || fail=1
+test "$(stat -c     %.6X k)" =    67413.023456        || fail=1
+test "$(stat -c     %.9X k)" =    67413.023456789     || fail=1
+test "$(stat -c   %13.6X k)" =  ' 67413.023456'       || fail=1
+test "$(stat -c  %013.6X k)" =   067413.023456        || fail=1
+test "$(stat -c  %-13.6X k)" =   '67413.023456 '      || fail=1
+test "$(stat -c  %18.10X k)" = '  67413.0234567890'   || fail=1
+test "$(stat -c %018.10X k)" =  0067413.0234567890    || fail=1
+test "$(stat -c %-18.10X k)" =   '67413.0234567890  ' || fail=1
 
 Exit $fail
diff --git a/tests/touch/60-seconds b/tests/touch/60-seconds
index d008296..e06c770 100755
--- a/tests/touch/60-seconds
+++ b/tests/touch/60-seconds
@@ -30,7 +30,7 @@ echo 60.000000000 > exp || framework_failure
 # an `invalid date format'.  Specifying 60 seconds *is* valid.
 TZ=UTC0 touch -t 197001010000.60 f || fail=1
 
-stat --p='%Y.%:Y\n' f > out || fail=1
+stat --p='%.9Y\n' f > out || fail=1
 
 compare out exp || fail=1
 
-- 
1.7.2






Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Sat, 06 Nov 2010 08:16:02 GMT) Full text and rfc822 format available.

Message #53 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: Eric Blake <eblake <at> redhat.com>, 7325 <at> debbugs.gnu.org,
	Pádraig Brady <P <at> draigBrady.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Sat, 06 Nov 2010 09:20:06 +0100
Paul Eggert wrote:

> On 11/04/2010 11:34 PM, Jim Meyering wrote:
>> Pádraig Brady wrote:
>>> I still slightly prefer just using %.X as
>>> it's backwards compat with older coreutils (excluding 8.6).
>>
>> So do I.
>
> I built that and tried it out, and found another problem that has been
> annoying me for years in other programs: 'stat' prints out unnecessary
> trailing zeros for time stamps, when the file system resolution is
> coarser than nanosecond resolution.  So I figured I'd fix that too,
> for 'stat' (other programs can be fixed later).  With this fix, %.X
> outputs the time stamp but omits trailing zeros if it can infer that
> the file system would always put zeros there.  If you want a specific
> number of zeros, you can use something like %.3X or %.9X (or %.100X :-).

Nice!

> Subject: [PATCH] stat: use e.g. %.3X instead of %X.%3:X for sub-second precision
>
> * NEWS: Document this.
> * doc/coreutils.texi (stat invocation): Likewise.
> * gl/lib/fstimeprec.c, gl/lib/fstimeprec.h, gl/modules/fstimeprec:
> * gl/modules/fstimeprec-tests, gl/tests/test-fstimeprec.c:
> New files.
> * bootstrap.conf (gnulib_modules): Add fstimeprec.
> * src/stat.c: Include fstimeprec.h.  Don't include xstrtol.h.
> (decimal_point, decimal_point_len): New static vars.
> (main): Initialize them.
> (epoch_sec, out_ns): Remove.
> (out_int, out_uint): Now returns whatever printf returned.
> (out_minus_zero, out_epoch_secs): New functions.
> (print_stat): Use out_epoch_sec instead of out_ns and epoch_sec.
> (print_stat, print_it, usage): Remove the %:X-style formats.
> * tests/misc/stat-nanoseconds: Set TZ=UTC0 to avoid problems
> with weird time zones.  Use a time stamp near the Epoch so that we
> don't have to worry about leap seconds.  Redo test cases to match

Both of those ideas seem useful enough to employ
in general, so I copied your log comments into the code.

> new behavior.
> * tests/touch/60-seconds: Change %Y.%:Y to %.9Y, to adjust to
> new behavior.

I haven't looked through all of it yet, but here's
a small change I'll fold in:

diff --git a/tests/misc/stat-nanoseconds b/tests/misc/stat-nanoseconds
index 9071ae9..0f41eb0 100755
--- a/tests/misc/stat-nanoseconds
+++ b/tests/misc/stat-nanoseconds
@@ -19,9 +19,11 @@
 test "$VERBOSE" = yes && stat --version
 . "${srcdir=.}/init.sh"; path_prepend_ ../src

+# Set this to avoid problems with weird time zones.
 TZ=UTC0
 export TZ

+# Use a time stamp near the Epoch to avoid trouble with leap seconds.
 touch -d '1970-01-01 18:43:33.023456789' k || framework_failure_

 ls --full-time | grep 18:43:33.023456789 \


FYI, after I push this, I'll update to the latest from gnulib
for strtod and icc-related fixes and make another snapshot.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Sat, 06 Nov 2010 09:17:02 GMT) Full text and rfc822 format available.

Message #56 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: Eric Blake <eblake <at> redhat.com>, 7325 <at> debbugs.gnu.org,
	Pádraig Brady <P <at> draigBrady.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Sat, 06 Nov 2010 10:21:03 +0100
Paul Eggert wrote:
...
> Subject: [PATCH] stat: use e.g. %.3X instead of %X.%3:X for sub-second precision

Thanks again.
Here's one more small change I'm including, to
put braces around this four-line "for"-loop body:
[per HACKING's "Curly braces" guidelines]

diff --git a/src/stat.c b/src/stat.c
index cbf6d25..99f115b 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -562,10 +562,12 @@ out_epoch_sec (char *pformat, size_t prefix_len, struct stat const *statbuf,
                     {
                       char *dst = pformat;
                       for (char const *src = dst; src < p; src++)
-                        if (*src == '-')
-                          frac_left_adjust = true;
-                        else
-                          *dst++ = *src;
+                        {
+                          if (*src == '-')
+                            frac_left_adjust = true;
+                          else
+                            *dst++ = *src;
+                        }
                       sec_prefix_len =
                         (dst - pformat
                          + (frac_left_adjust ? 0 : sprintf (dst, "%d", w)));




Reply sent to Pádraig Brady <P <at> draigBrady.com>:
You have taken responsibility. (Sat, 06 Nov 2010 14:17:01 GMT) Full text and rfc822 format available.

Notification sent to Jim Meyering <jim <at> meyering.net>:
bug acknowledged by developer. (Sat, 06 Nov 2010 14:17:02 GMT) Full text and rfc822 format available.

Message #61 received at 7325-done <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 7325-done <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>,
	Jim Meyering <jim <at> meyering.net>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Sat, 06 Nov 2010 14:20:50 +0000
 On 06/11/10 02:54, Paul Eggert wrote:
> On 11/04/2010 11:34 PM, Jim Meyering wrote:
>> Pádraig Brady wrote:
>>> I still slightly prefer just using %.X as
>>> it's backwards compat with older coreutils (excluding 8.6).
>>
>> So do I.
> 
> I built that and tried it out, and found another problem that has been
> annoying me for years in other programs: 'stat' prints out unnecessary
> trailing zeros for time stamps, when the file system resolution is
> coarser than nanosecond resolution.  So I figured I'd fix that too,
> for 'stat' (other programs can be fixed later).  With this fix, %.X
> outputs the time stamp but omits trailing zeros if it can infer that
> the file system would always put zeros there.  If you want a specific
> number of zeros, you can use something like %.3X or %.9X (or %.100X :-).

Interesting. So it's variable precision by default

$ touch -d '1970-01-01 18:43:33.5000000000' 2; ~/git/t/coreutils/src/stat -c "%.W %.X %.Y %.Z" 2
0.000000000 63813.500000000 63813.500000000 1289052572.699980883
$ touch -d '1970-01-01 18:43:33.5000000000' 2; ~/git/t/coreutils/src/stat -c "%.W %.X %.Y %.Z" 2
0.00000000 63813.50000000 63813.50000000 1289052573.53698077

I like it.

BTW you dropped a blank line at the end of the NEWS section.

cheers,
Pádraig.

p.s. I'm marking this bug as done




Message #62 received at 7325-done <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: 7325-done <at> debbugs.gnu.org, Paul Eggert <eggert <at> cs.ucla.edu>,
	Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Sat, 06 Nov 2010 15:37:44 +0100
Pádraig Brady wrote:
>  On 06/11/10 02:54, Paul Eggert wrote:
>> On 11/04/2010 11:34 PM, Jim Meyering wrote:
>>> Pádraig Brady wrote:
>>>> I still slightly prefer just using %.X as
>>>> it's backwards compat with older coreutils (excluding 8.6).
>>>
>>> So do I.
>>
>> I built that and tried it out, and found another problem that has been
>> annoying me for years in other programs: 'stat' prints out unnecessary
>> trailing zeros for time stamps, when the file system resolution is
>> coarser than nanosecond resolution.  So I figured I'd fix that too,
>> for 'stat' (other programs can be fixed later).  With this fix, %.X
>> outputs the time stamp but omits trailing zeros if it can infer that
>> the file system would always put zeros there.  If you want a specific
>> number of zeros, you can use something like %.3X or %.9X (or %.100X :-).
>
> Interesting. So it's variable precision by default
>
> $ touch -d '1970-01-01 18:43:33.5000000000' 2; ~/git/t/coreutils/src/stat -c "%.W %.X %.Y %.Z" 2
> 0.000000000 63813.500000000 63813.500000000 1289052572.699980883
> $ touch -d '1970-01-01 18:43:33.5000000000' 2; ~/git/t/coreutils/src/stat -c "%.W %.X %.Y %.Z" 2
> 0.00000000 63813.50000000 63813.50000000 1289052573.53698077
>
> I like it.
>
> BTW you dropped a blank line at the end of the NEWS section.

Good catch.  I've adjusted his patch.

That happens regularly, so we should add a check for this.
Here's a start:

sed -n 4,/Noteworthy/p NEWS| perl -n0e '/\n\n\n\* Noteworthy.*$/ or die'

> p.s. I'm marking this bug as done

Thanks.

BTW, I've just pushed Paul's patch and the fix for FreeBSD's /bin/sh bug,
and made a snapshot.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Mon, 08 Nov 2010 12:56:02 GMT) Full text and rfc822 format available.

Message #65 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: 7325 <at> debbugs.gnu.org, Paul Eggert <eggert <at> CS.UCLA.EDU>, 
	Jim Meyering <jim <at> meyering.net>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Mon, 08 Nov 2010 12:59:51 +0000
On 06/11/10 14:20, Pádraig Brady wrote:
>  On 06/11/10 02:54, Paul Eggert wrote:
>> On 11/04/2010 11:34 PM, Jim Meyering wrote:
>>> Pádraig Brady wrote:
>>>> I still slightly prefer just using %.X as
>>>> it's backwards compat with older coreutils (excluding 8.6).
>>>
>>> So do I.
>>
>> I built that and tried it out, and found another problem that has been
>> annoying me for years in other programs: 'stat' prints out unnecessary
>> trailing zeros for time stamps, when the file system resolution is
>> coarser than nanosecond resolution.  So I figured I'd fix that too,
>> for 'stat' (other programs can be fixed later).  With this fix, %.X
>> outputs the time stamp but omits trailing zeros if it can infer that
>> the file system would always put zeros there.  If you want a specific
>> number of zeros, you can use something like %.3X or %.9X (or %.100X :-).
> 
> Interesting. So it's variable precision by default
> 
> $ touch -d '1970-01-01 18:43:33.5000000000' 2; ~/git/t/coreutils/src/stat -c "%.W %.X %.Y %.Z" 2
> 0.000000000 63813.500000000 63813.500000000 1289052572.699980883
> $ touch -d '1970-01-01 18:43:33.5000000000' 2; ~/git/t/coreutils/src/stat -c "%.W %.X %.Y %.Z" 2
> 0.00000000 63813.50000000 63813.50000000 1289052573.53698077
> 
> I like it.

One caveat we should at least document is
we can't rely on string comparison of timestamps.
I.E. shell code like this could fail, because
a change in atime for example, could cause
a change in the returned mtime.

# Wait for file to be modified
"$ts" = $(stat -c "%.Y" file)
while [ "$ts" = $(stat -c "%.Y" file) ]; do sleep .1; done

cheers,
Pádraig.

From 42d77a300234f608b71c46f6a39bb3a1f4cb31d3 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?P=C3=A1draig=20Brady?= <P <at> draigBrady.com>
Date: Mon, 8 Nov 2010 12:49:30 +0000
Subject: [PATCH] doc: mention a caveat with the new sub-second precision stat format

* doc/coreutils.texi (stat invocation): Dissuade the use of
the auto precision format with subsequent string comparisons.
---
 doc/coreutils.texi |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 8dfb069..e310c33 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -10721,7 +10721,9 @@ print after the decimal point. For example, @samp{%.9X} outputs the
 last access time to nanosecond precision.  If a period is given but no
 precision, @command{stat} uses the estimated precision of the file
 system. When discarding excess precision, time stamps are truncated
-toward minus infinity.
+toward minus infinity.  Since this estimated precision can return
+differing numbers of trailing zeros, the result should not be used
+with string comparison operators in shell scripts for example.

 @example
 zero pad:
-- 
1.6.2.5




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Mon, 08 Nov 2010 14:29:02 GMT) Full text and rfc822 format available.

Message #68 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: Paul Eggert <eggert <at> CS.UCLA.EDU>, 7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Mon, 08 Nov 2010 15:33:02 +0100
Pádraig Brady wrote:
> On 06/11/10 14:20, Pádraig Brady wrote:
>>  On 06/11/10 02:54, Paul Eggert wrote:
>>> On 11/04/2010 11:34 PM, Jim Meyering wrote:
>>>> Pádraig Brady wrote:
>>>>> I still slightly prefer just using %.X as
>>>>> it's backwards compat with older coreutils (excluding 8.6).
>>>>
>>>> So do I.
>>>
>>> I built that and tried it out, and found another problem that has been
>>> annoying me for years in other programs: 'stat' prints out unnecessary
>>> trailing zeros for time stamps, when the file system resolution is
>>> coarser than nanosecond resolution.  So I figured I'd fix that too,
>>> for 'stat' (other programs can be fixed later).  With this fix, %.X
>>> outputs the time stamp but omits trailing zeros if it can infer that
>>> the file system would always put zeros there.  If you want a specific
>>> number of zeros, you can use something like %.3X or %.9X (or %.100X :-).
>>
>> Interesting. So it's variable precision by default
>>
>> $ touch -d '1970-01-01 18:43:33.5000000000' 2; ~/git/t/coreutils/src/stat -c "%.W %.X %.Y %.Z" 2
>> 0.000000000 63813.500000000 63813.500000000 1289052572.699980883
>> $ touch -d '1970-01-01 18:43:33.5000000000' 2; ~/git/t/coreutils/src/stat -c "%.W %.X %.Y %.Z" 2
>> 0.00000000 63813.50000000 63813.50000000 1289052573.53698077
>>
>> I like it.
>
> One caveat we should at least document is
> we can't rely on string comparison of timestamps.
> I.E. shell code like this could fail, because
> a change in atime for example, could cause
> a change in the returned mtime.
>
> # Wait for file to be modified
> "$ts" = $(stat -c "%.Y" file)
> while [ "$ts" = $(stat -c "%.Y" file) ]; do sleep .1; done

That's a compelling argument.
It'd be very easy to write a script like that
after seeing this sentence in NEWS:

    To obtain a full resolution time stamp for %X, use %.X;

Viewed like that, it feels like we're providing a little
too much rope here, and already nicely knotted and ready for use.

I don't like seeing fewer digits of mtime precision just
because atime nanoseconds happens to be a multiple of 10.
Of course that happens in only ~1-in-10 times, and then only when
the other nanosecond parts are in the same boat (see contrived
example below).
Then there are the even less frequent cases of 7 digits.

Looks like I got very lucky here and hit a number of nanoseconds
that happened to be a multiple of 100,000:

    $ for i in $(seq 1000); do touch -d '1970-01-01 18:43:33.5000000000' 2; t=$(stat -c "%.W %.X %.Y %.Z" 2); test $(echo "$t"|wc -c) -lt 57 && echo "$t"; done
    0.000000 63813.500000 63813.500000 1289224045.731146
    0.0000 63813.5000 63813.5000 1289224047.8224
    [Exit 1]

I realize this is due to the way the precision estimation
heuristic works.  Wondering if there's a less-surprising
way to do that.

Now, I'm thinking that this variable precision feature would be better
if it were somehow optional, rather than the default for %.X.
Consistency/reproducibility are more important, here.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Mon, 08 Nov 2010 15:19:02 GMT) Full text and rfc822 format available.

Message #71 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Jim Meyering <jim <at> meyering.net>
Cc: Paul Eggert <eggert <at> CS.UCLA.EDU>, 7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Mon, 08 Nov 2010 15:22:07 +0000
On 08/11/10 14:33, Jim Meyering wrote:
> Looks like I got very lucky here and hit a number of nanoseconds
> that happened to be a multiple of 100,000:
> 
>     $ for i in $(seq 1000); do touch -d '1970-01-01 18:43:33.5000000000' 2; t=$(stat -c "%.W %.X %.Y %.Z" 2); test $(echo "$t"|wc -c) -lt 57 && echo "$t"; done
>     0.000000 63813.500000 63813.500000 1289224045.731146
>     0.0000 63813.5000 63813.5000 1289224047.8224
>     [Exit 1]
> 
> I realize this is due to the way the precision estimation
> heuristic works.  Wondering if there's a less-surprising
> way to do that.

You could snap to milli, micro, nano,
though that would just mean it would
happen less often.

> Now, I'm thinking that this variable precision feature would be better
> if it were somehow optional, rather than the default for %.X.
> Consistency/reproducibility are more important, here.

You could touch -d '0.123456789' stat.prec.test
at program start, but that wouldn't always work.
Non writable dir, disparity between read and
write support for time stamp resolutions, :(

You could sample X preexisting files/dirs on the
same file system, and stop when Y have not increased
in precision. That combined with snapping to milli,micro,nano
would usually work. Though that's starting to
get too hacky IMHO while still not being general.

I guess we're back to doing 9 by default for %.Y
and using %#.Y to mean auto precision ?

cheers,
Pádraig.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Mon, 08 Nov 2010 15:27:02 GMT) Full text and rfc822 format available.

Message #74 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: Paul Eggert <eggert <at> CS.UCLA.EDU>, 7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Mon, 08 Nov 2010 16:31:21 +0100
Pádraig Brady wrote:

> On 08/11/10 14:33, Jim Meyering wrote:
>> Looks like I got very lucky here and hit a number of nanoseconds
>> that happened to be a multiple of 100,000:
>>
>>     $ for i in $(seq 1000); do touch -d '1970-01-01 18:43:33.5000000000' 2; t=$(stat -c "%.W %.X %.Y %.Z" 2); test $(echo "$t"|wc -c) -lt 57 && echo "$t"; done
>>     0.000000 63813.500000 63813.500000 1289224045.731146
>>     0.0000 63813.5000 63813.5000 1289224047.8224
>>     [Exit 1]
>>
>> I realize this is due to the way the precision estimation
>> heuristic works.  Wondering if there's a less-surprising
>> way to do that.
>
> You could snap to milli, micro, nano,
> though that would just mean it would
> happen less often.
>
>> Now, I'm thinking that this variable precision feature would be better
>> if it were somehow optional, rather than the default for %.X.
>> Consistency/reproducibility are more important, here.
>
> You could touch -d '0.123456789' stat.prec.test
> at program start, but that wouldn't always work.
> Non writable dir, disparity between read and
> write support for time stamp resolutions, :(
>
> You could sample X preexisting files/dirs on the
> same file system, and stop when Y have not increased
> in precision. That combined with snapping to milli,micro,nano
> would usually work. Though that's starting to
> get too hacky IMHO while still not being general.

I agree.
The only possibility I can imagine is to use some sort of statfs-like
interface that would provide file system time stamp resolution.

> I guess we're back to doing 9 by default for %.Y
> and using %#.Y to mean auto precision ?

The default of 9 seems far less likely to cause subtle misuse.
Letting the "#" in %#.Y mean auto precision sounds appropriate.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Mon, 08 Nov 2010 15:58:01 GMT) Full text and rfc822 format available.

Message #77 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Eric Blake <eblake <at> redhat.com>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: Paul Eggert <eggert <at> CS.UCLA.EDU>, 7325 <at> debbugs.gnu.org,
	Jim Meyering <jim <at> meyering.net>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Mon, 08 Nov 2010 09:02:03 -0700
[Message part 1 (text/plain, inline)]
On 11/08/2010 08:22 AM, Pádraig Brady wrote:
> On 08/11/10 14:33, Jim Meyering wrote:
>> Looks like I got very lucky here and hit a number of nanoseconds
>> that happened to be a multiple of 100,000:
>>
>>     $ for i in $(seq 1000); do touch -d '1970-01-01 18:43:33.5000000000' 2; t=$(stat -c "%.W %.X %.Y %.Z" 2); test $(echo "$t"|wc -c) -lt 57 && echo "$t"; done
>>     0.000000 63813.500000 63813.500000 1289224045.731146
>>     0.0000 63813.5000 63813.5000 1289224047.8224
>>     [Exit 1]
>>
>> I realize this is due to the way the precision estimation
>> heuristic works.  Wondering if there's a less-surprising
>> way to do that.
> 
> You could snap to milli, micro, nano,
> though that would just mean it would
> happen less often.

On cygwin, the default precision is 100nano (that is, 7 digits).

See also gnulib/lib/utimecmp.c, which also sets up a hash table that
tries to determine a file system's default resolution.  In particular,
it makes 100% correct analysis on file systems that support
_PC_TIMESTAMP_RESOLUTION, but that's still pretty rare today.

In fact, since Paul originally wrote utimecmp.c, I'm surprised that you
rewrote the coreutils hash table from scratch rather than trying to
reuse the code.

-- 
Eric Blake   eblake <at> redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

[signature.asc (application/pgp-signature, attachment)]

Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Tue, 09 Nov 2010 00:55:02 GMT) Full text and rfc822 format available.

Message #80 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eric Blake <eblake <at> redhat.com>
Cc: 7325 <at> debbugs.gnu.org, Pádraig Brady <P <at> draigBrady.com>,
	Jim Meyering <jim <at> meyering.net>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Mon, 08 Nov 2010 16:59:15 -0800
On 11/08/10 08:02, Eric Blake wrote:
> In fact, since Paul originally wrote utimecmp.c, I'm surprised that you
> rewrote the coreutils hash table from scratch rather than trying to
> reuse the code.

I had vaguely remembered the issue, but I had forgotten where I put
that code.  utimecmp.c modifies the time stamp of the files, right?
So it might not be a good idea here.  But perhaps some of the common
code could be factored out.

Getting back to the point: I don't see a problem with 'stat' backward compatibility.
The guessed-resolution time stamps are output only if someone uses "%.X",
which is a format that nobody would use before the change.  So old
scripts shouldn't be broken by the change.

So it sounds like the issue is mostly about new scripts.  But for
those, we can tell people not to use "%.X" if they want to do textual
comparison.  Advice along these lines will be needed no matter what,
because, even if we could determine timestamp resolution perfectly,
there would still be a problem with blind use of "%.X".  Suppose someone
did something like this:

	ts=$(stat -c %.Y $old)
	cp -p $old $new
	# Wait for $new to be modified
	while [ $ts = $(stat -c %.Y $new) ]; do sleep .1; done

This won't work as desired even if stat could deduce timestamp resolution
perfectly, because $old and $new could be on different file systems,
and $new's file system could have a coarser resolution than $old's.

I can write a documentation patch along these lines if you like.





Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Tue, 09 Nov 2010 06:50:02 GMT) Full text and rfc822 format available.

Message #83 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: Pádraig Brady <P <at> draigBrady.com>, 7325 <at> debbugs.gnu.org,
	Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Tue, 09 Nov 2010 07:54:30 +0100
Paul Eggert wrote:

> On 11/08/10 08:02, Eric Blake wrote:
>> In fact, since Paul originally wrote utimecmp.c, I'm surprised that you
>> rewrote the coreutils hash table from scratch rather than trying to
>> reuse the code.
>
> I had vaguely remembered the issue, but I had forgotten where I put
> that code.  utimecmp.c modifies the time stamp of the files, right?
> So it might not be a good idea here.  But perhaps some of the common
> code could be factored out.
>
> Getting back to the point: I don't see a problem with 'stat' backward compatibility.
> The guessed-resolution time stamps are output only if someone uses "%.X",
> which is a format that nobody would use before the change.  So old
> scripts shouldn't be broken by the change.
>
> So it sounds like the issue is mostly about new scripts.  But for

Yes.

> those, we can tell people not to use "%.X" if they want to do textual

The semantics of this feature feel rather involved for something that
looks like a simple default.  Some will not read the caveat.

> comparison.  Advice along these lines will be needed no matter what,
> because, even if we could determine timestamp resolution perfectly,
> there would still be a problem with blind use of "%.X".  Suppose someone
> did something like this:
>
> 	ts=$(stat -c %.Y $old)
> 	cp -p $old $new
> 	# Wait for $new to be modified
> 	while [ $ts = $(stat -c %.Y $new) ]; do sleep .1; done
>
> This won't work as desired even if stat could deduce timestamp resolution
> perfectly, because $old and $new could be on different file systems,
> and $new's file system could have a coarser resolution than $old's.
>
> I can write a documentation patch along these lines if you like.

Isn't this a good reason to attach the variable-width functionality
to a less-likely-to-be-(ab)used syntax like "%#.X"?  Then we would put
that format directive in the default format string, where its output
is parsed only by humans, and scripts using the shorter %.X
would be less error prone.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Wed, 10 Nov 2010 09:01:02 GMT) Full text and rfc822 format available.

Message #86 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: P, ádraig Brady <P <at> draigBrady.com>,
	7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Wed, 10 Nov 2010 10:04:52 +0100
Jim Meyering wrote:

> Paul Eggert wrote:
>
>> On 11/08/10 08:02, Eric Blake wrote:
>>> In fact, since Paul originally wrote utimecmp.c, I'm surprised that you
>>> rewrote the coreutils hash table from scratch rather than trying to
>>> reuse the code.
>>
>> I had vaguely remembered the issue, but I had forgotten where I put
>> that code.  utimecmp.c modifies the time stamp of the files, right?
>> So it might not be a good idea here.  But perhaps some of the common
>> code could be factored out.
>>
>> Getting back to the point: I don't see a problem with 'stat'
>> backward compatibility.
>> The guessed-resolution time stamps are output only if someone uses "%.X",
>> which is a format that nobody would use before the change.  So old
>> scripts shouldn't be broken by the change.
>>
>> So it sounds like the issue is mostly about new scripts.  But for
>
> Yes.
>
>> those, we can tell people not to use "%.X" if they want to do textual
>
> The semantics of this feature feel rather involved for something that
> looks like a simple default.  Some will not read the caveat.
>
>> comparison.  Advice along these lines will be needed no matter what,
>> because, even if we could determine timestamp resolution perfectly,
>> there would still be a problem with blind use of "%.X".  Suppose someone
>> did something like this:
>>
>> 	ts=$(stat -c %.Y $old)
>> 	cp -p $old $new
>> 	# Wait for $new to be modified
>> 	while [ $ts = $(stat -c %.Y $new) ]; do sleep .1; done
>>
>> This won't work as desired even if stat could deduce timestamp resolution
>> perfectly, because $old and $new could be on different file systems,
>> and $new's file system could have a coarser resolution than $old's.
>>
>> I can write a documentation patch along these lines if you like.
>
> Isn't this a good reason to attach the variable-width functionality
> to a less-likely-to-be-(ab)used syntax like "%#.X"?  Then we would put
> that format directive in the default format string, where its output
> is parsed only by humans, and scripts using the shorter %.X
> would be less error prone.

Unless I hear otherwise soon, I'll use something like
the following basis for the proposed change:
(of course, this needs additional tests and probably documentation changes)

diff --git a/src/stat.c b/src/stat.c
index ae7ce02..98b7501 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -550,18 +550,27 @@ out_epoch_sec (char *pformat, size_t prefix_len, struct stat const *statbuf,
       sec_prefix_len = dot - pformat;
       pformat[prefix_len] = '\0';

+      /* %.X   => precision defaults to 9
+         %.5X  => precision is 5
+         %#.X  => precision is determined by fstimeprec
+         %#.3X => precision is 3 (specified overrides "#")  */
+
       if (ISDIGIT (dot[1]))
         {
           long int lprec = strtol (dot + 1, NULL, 10);
           precision = (lprec <= INT_MAX ? lprec : INT_MAX);
         }
-      else
+      else if (memchr (pformat, '#', dot - pformat))
         {
           static struct fstimeprec *tab;
           if (! tab)
             tab = fstimeprec_alloc ();
           precision = fstimeprec (tab, statbuf);
         }
+      else
+        {
+          precision = 9;
+        }

       if (precision && ISDIGIT (dot[-1]))
         {




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 11 Nov 2010 07:08:01 GMT) Full text and rfc822 format available.

Message #89 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Jim Meyering <jim <at> meyering.net>
Cc: Pád, raig Brady <P <at> draigBrady.com>,
	7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Wed, 10 Nov 2010 23:11:58 -0800
On 11/10/2010 01:04 AM, Jim Meyering wrote:
> +      /* %.X   => precision defaults to 9
> +         %.5X  => precision is 5
> +         %#.X  => precision is determined by fstimeprec
> +         %#.3X => precision is 3 (specified overrides "#")  */

How about something like this instead?

  %.X => precision is 9 (until POSIX goes sub-nanosecond :-)
  %.5X => precision is 5
  %.*X => precision determined by fstimeprec

Then there's no reason for the "overrides" case.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 11 Nov 2010 11:45:02 GMT) Full text and rfc822 format available.

Message #92 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: P, ádraig Brady <P <at> draigBrady.com>,
	7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 11 Nov 2010 12:49:10 +0100
Paul Eggert wrote:

> On 11/10/2010 01:04 AM, Jim Meyering wrote:
>> +      /* %.X   => precision defaults to 9
>> +         %.5X  => precision is 5
>> +         %#.X  => precision is determined by fstimeprec
>> +         %#.3X => precision is 3 (specified overrides "#")  */
>
> How about something like this instead?
>
>   %.X => precision is 9 (until POSIX goes sub-nanosecond :-)
>   %.5X => precision is 5
>   %.*X => precision determined by fstimeprec
>
> Then there's no reason for the "overrides" case.

Good idea.  I prefer that.

From 26e466e056462448e81536d9a96499fbe1f725ef Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering <at> redhat.com>
Date: Wed, 10 Nov 2010 12:28:30 +0100
Subject: [PATCH] stat: default to precision=9; now %.*X uses variable

---
 src/stat.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/stat.c b/src/stat.c
index ae7ce02..7ceb9c1 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -550,18 +550,26 @@ out_epoch_sec (char *pformat, size_t prefix_len, struct stat const *statbuf,
       sec_prefix_len = dot - pformat;
       pformat[prefix_len] = '\0';

+      /* %.X   => precision defaults to 9
+         %.5X  => precision is 5
+         %.*X  => precision is determined by fstimeprec */
+
       if (ISDIGIT (dot[1]))
         {
           long int lprec = strtol (dot + 1, NULL, 10);
           precision = (lprec <= INT_MAX ? lprec : INT_MAX);
         }
-      else
+      else if (dot[1] == '*')
         {
           static struct fstimeprec *tab;
           if (! tab)
             tab = fstimeprec_alloc ();
           precision = fstimeprec (tab, statbuf);
         }
+      else
+        {
+          precision = 9;
+        }

       if (precision && ISDIGIT (dot[-1]))
         {
@@ -1061,7 +1069,8 @@ print_it (char const *format, char const *filename,
             char const *fmt_char = b + len + 1;
             fmt_char += strspn (fmt_char, digits);
             if (*fmt_char == '.')
-              fmt_char += 1 + strspn (fmt_char + 1, digits);
+              fmt_char += 1 + (fmt_char[1] == '*'
+                               ? 1 : strspn (fmt_char + 1, digits));
             len = fmt_char - (b + 1);
             unsigned int fmt_code = *fmt_char;
             memcpy (dest, b, len + 1);
--
1.7.3.2.4.g60aa9




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 11 Nov 2010 12:01:02 GMT) Full text and rfc822 format available.

Message #95 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Jim Meyering <jim <at> meyering.net>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, Eric Blake <eblake <at> redhat.com>,
	7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 11 Nov 2010 12:04:47 +0000
On 11/11/10 11:49, Jim Meyering wrote:
> Paul Eggert wrote:
> 
>> On 11/10/2010 01:04 AM, Jim Meyering wrote:
>>> +      /* %.X   => precision defaults to 9
>>> +         %.5X  => precision is 5
>>> +         %#.X  => precision is determined by fstimeprec
>>> +         %#.3X => precision is 3 (specified overrides "#")  */
>>
>> How about something like this instead?
>>
>>   %.X => precision is 9 (until POSIX goes sub-nanosecond :-)
>>   %.5X => precision is 5
>>   %.*X => precision determined by fstimeprec
>>
>> Then there's no reason for the "overrides" case.
> 
> Good idea.  I prefer that.

Well the reason I chose %#.X was that it was the
standard mechanism for choosing "alternate form"
and so was backwards compat with previous stats.
I.E. on any stat "%#.X" would give the best
available precision.

cheers,
Pádraig.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 11 Nov 2010 13:22:01 GMT) Full text and rfc822 format available.

Message #98 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, Eric Blake <eblake <at> redhat.com>,
	7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 11 Nov 2010 14:25:55 +0100
Pádraig Brady wrote:

> On 11/11/10 11:49, Jim Meyering wrote:
>> Paul Eggert wrote:
>>
>>> On 11/10/2010 01:04 AM, Jim Meyering wrote:
>>>> +      /* %.X   => precision defaults to 9
>>>> +         %.5X  => precision is 5
>>>> +         %#.X  => precision is determined by fstimeprec
>>>> +         %#.3X => precision is 3 (specified overrides "#")  */
>>>
>>> How about something like this instead?
>>>
>>>   %.X => precision is 9 (until POSIX goes sub-nanosecond :-)
>>>   %.5X => precision is 5
>>>   %.*X => precision determined by fstimeprec
>>>
>>> Then there's no reason for the "overrides" case.
>>
>> Good idea.  I prefer that.
>
> Well the reason I chose %#.X was that it was the
> standard mechanism for choosing "alternate form"
> and so was backwards compat with previous stats.
> I.E. on any stat "%#.X" would give the best
> available precision.

I prefer the "%.*X" notation because things to the right of the "."
denote precision.  It's slightly odd in that it looks like the invoker
might provide the actual number somehow, but once you know the rule
that precision comes from fstimeprec, it makes sense.

for i in $(seq 10); do
  touch -d '1970-01-01 18:43:33.5000000000' k
  src/stat -c "%.*Y" k
done

...
63813.50000000
63813.500000000
63813.5000000
63813.500000000




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 11 Nov 2010 13:50:03 GMT) Full text and rfc822 format available.

Message #101 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, Eric Blake <eblake <at> redhat.com>,
	7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 11 Nov 2010 14:54:40 +0100
Pádraig Brady wrote:

> On 11/11/10 11:49, Jim Meyering wrote:
>> Paul Eggert wrote:
>>
>>> On 11/10/2010 01:04 AM, Jim Meyering wrote:
>>>> +      /* %.X   => precision defaults to 9
>>>> +         %.5X  => precision is 5
>>>> +         %#.X  => precision is determined by fstimeprec
>>>> +         %#.3X => precision is 3 (specified overrides "#")  */
>>>
>>> How about something like this instead?
>>>
>>>   %.X => precision is 9 (until POSIX goes sub-nanosecond :-)
>>>   %.5X => precision is 5
>>>   %.*X => precision determined by fstimeprec
>>>
>>> Then there's no reason for the "overrides" case.
>>
>> Good idea.  I prefer that.
...

Regardless, of syntax, can any of you suggest a good way to test this?
I can think of a few, but each has disadvantages.

  - mount an ext2 file system and ensure that there are no nanoseconds
     Pro: works all the time, as long as ext2 is an option
     Con: root-only and requires mkfs.ext2

     Code:
        dd if=/dev/zero of=blob count=2 seek=2M > /dev/null || skip=1
        mkdir mnt || skip=1
        mkfs -t ext2 -F blob \
          || skip_test_ "failed to create ext2 file system"
        mount -oloop blob mnt || skip=1
        touch -d '1970-01-01 18:43:33.5000000000' k || fail=1
        test "$(stat -c '%.*Y' k)" = 63813 || fail=1

  - require a modern file system type and run a loop like this,
    hoping to find a time stamp with fewer than "normal" digits of
    nanosecond precision.

      $ for i in $(seq 10); do rm -f k; touch -d '1970-01-01 18:43:33.5000000000' k; /cu/src/stat -c "%.*Y" k; done
      63813.500000000
      63813.50000000
      63813.500000000
      63813.500000000
      63813.500000000
      63813.50000000
      63813.500000000
      63813.500000000
      63813.500000000
      63813.500000000

    Pro: does not require mount privileges
    Con: I suppose it may fail some of the time, no matter how many
         iterations we perform.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 11 Nov 2010 14:23:02 GMT) Full text and rfc822 format available.

Message #104 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Jim Meyering <jim <at> meyering.net>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, Eric Blake <eblake <at> redhat.com>,
	7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 11 Nov 2010 14:26:55 +0000
On 11/11/10 12:04, Pádraig Brady wrote:
> On 11/11/10 11:49, Jim Meyering wrote:
>> Paul Eggert wrote:
>>
>>> On 11/10/2010 01:04 AM, Jim Meyering wrote:
>>>> +      /* %.X   => precision defaults to 9
>>>> +         %.5X  => precision is 5
>>>> +         %#.X  => precision is determined by fstimeprec
>>>> +         %#.3X => precision is 3 (specified overrides "#")  */
>>>
>>> How about something like this instead?
>>>
>>>   %.X => precision is 9 (until POSIX goes sub-nanosecond :-)
>>>   %.5X => precision is 5
>>>   %.*X => precision determined by fstimeprec
>>>
>>> Then there's no reason for the "overrides" case.
>>
>> Good idea.  I prefer that.
> 
> Well the reason I chose %#.X was that it was the
> standard mechanism for choosing "alternate form"
> and so was backwards compat with previous stats.
> I.E. on any stat "%#.X" would give the best
> available precision.

An alternative perhaps that doesn't require the above override
behavior and is also forwards compat, is to use %.0X rather than %.*X
I.E. 0 selects the auto precision, and if you really don't
want any decimal places then don't use "." at all?

I don't feel strongly about any of these.
I slightly prefer being forwardss compat though.
I.E. that old versions of stat work with newer scripts.

cheers,
Pádraig.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 11 Nov 2010 14:51:02 GMT) Full text and rfc822 format available.

Message #107 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Jim Meyering <jim <at> meyering.net>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, Eric Blake <eblake <at> redhat.com>,
	7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 11 Nov 2010 14:54:47 +0000
On 11/11/10 13:54, Jim Meyering wrote:
> Pádraig Brady wrote:
> 
>> On 11/11/10 11:49, Jim Meyering wrote:
>>> Paul Eggert wrote:
>>>
>>>> On 11/10/2010 01:04 AM, Jim Meyering wrote:
>>>>> +      /* %.X   => precision defaults to 9
>>>>> +         %.5X  => precision is 5
>>>>> +         %#.X  => precision is determined by fstimeprec
>>>>> +         %#.3X => precision is 3 (specified overrides "#")  */
>>>>
>>>> How about something like this instead?
>>>>
>>>>   %.X => precision is 9 (until POSIX goes sub-nanosecond :-)
>>>>   %.5X => precision is 5
>>>>   %.*X => precision determined by fstimeprec
>>>>
>>>> Then there's no reason for the "overrides" case.
>>>
>>> Good idea.  I prefer that.
> ...
> 
> Regardless, of syntax, can any of you suggest a good way to test this?
> I can think of a few, but each has disadvantages.
> 
>   - mount an ext2 file system and ensure that there are no nanoseconds
>      Pro: works all the time, as long as ext2 is an option
>      Con: root-only and requires mkfs.ext2
> 
>      Code:
>         dd if=/dev/zero of=blob count=2 seek=2M > /dev/null || skip=1
>         mkdir mnt || skip=1
>         mkfs -t ext2 -F blob \
>           || skip_test_ "failed to create ext2 file system"
>         mount -oloop blob mnt || skip=1
>         touch -d '1970-01-01 18:43:33.5000000000' k || fail=1
>         test "$(stat -c '%.*Y' k)" = 63813 || fail=1
> 
>   - require a modern file system type and run a loop like this,
>     hoping to find a time stamp with fewer than "normal" digits of
>     nanosecond precision.
> 
>       $ for i in $(seq 10); do rm -f k; touch -d '1970-01-01 18:43:33.5000000000' k; /cu/src/stat -c "%.*Y" k; done
>       63813.500000000
>       63813.50000000
>       63813.500000000
>       63813.500000000
>       63813.500000000
>       63813.50000000
>       63813.500000000
>       63813.500000000
>       63813.500000000
>       63813.500000000
> 
>     Pro: does not require mount privileges
>     Con: I suppose it may fail some of the time, no matter how many
>          iterations we perform.
> 

I prefer the latter.
It's quick to run so do it 100 times

require_nanosecond_fs_

# Set this to avoid problems with weird time zones.
TZ=UTC0
export TZ

# Use a time stamp near the Epoch to avoid trouble with leap seconds.
touch -d '1970-01-01 18:43:33.5' k || framework_failure_

prec=$(for i in $(seq 100); do
         touch -a k; stat -c "%.*Y" k
       done | cut -d. -f2 | wc -L)
test "$prec" = 9 || fail=1




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 11 Nov 2010 15:21:01 GMT) Full text and rfc822 format available.

Message #110 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Eric Blake <eblake <at> redhat.com>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, 7325 <at> debbugs.gnu.org,
	Jim Meyering <jim <at> meyering.net>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 11 Nov 2010 08:24:52 -0700
[Message part 1 (text/plain, inline)]
On 11/11/2010 07:26 AM, Pádraig Brady wrote:
>>>>   %.*X => precision determined by fstimeprec
>>>>
> 
> An alternative perhaps that doesn't require the above override
> behavior and is also forwards compat, is to use %.0X rather than %.*X

That sounds nicer to me.  I look at %.*X and think I have to supply the
precision, but %.0X as a mnemonic of 'show full precision but suppress
trailing zeros' kind of makes sense, and looks nicer than %#.X.

-- 
Eric Blake   eblake <at> redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

[signature.asc (application/pgp-signature, attachment)]

Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 11 Nov 2010 17:50:03 GMT) Full text and rfc822 format available.

Message #113 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eric Blake <eblake <at> redhat.com>
Cc: 7325 <at> debbugs.gnu.org, Pádraig Brady <P <at> draigBrady.com>,
	Jim Meyering <jim <at> meyering.net>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 11 Nov 2010 09:54:14 -0800
On 11/11/2010 07:24 AM, Eric Blake wrote:
> %.0X as a mnemonic of 'show full precision but suppress
> trailing zeros' kind of makes sense

I had considered supporting those semantics
as well, which would have avoided all this business with
fstimeprec.  That is, just trim trailing zeros, and don't
worry about the file system time stamp resolution.  The problem
with this approach is that different time stamps for the same
file (atime, mtime, ctime) might show different numbers of digits,
which might cause alignment problems and confusion.

I'm a bit leery of %.0X as meaning "show more than zero digits
of precision", since .0 always means show zero everywhere else
that printf-style formats are used.

I'm still not quite following the backward compatibility argument,
as no matter what we do, we'll have different functionality than
before.  %#.X outputs an integer time stamp with coreutils 5.97
and outputs nothing with coreutils 8.6.  %.0X is the same as
%#.X, so they're both equally "bad" in that respect.  %.*X outputs
"*X" with 5.97 and "?X" with 8.6, so it's not portable either.  It's
not a big deal, but I still mildly prefer the * notation.

By the way, while we're on the subject (:-), 'stat' uses wildly
different strategies when dealing with invalid formats.
Sometimes it outputs a diagnostic, sometimes it silently
outputs a question mark, sometimes it silently outputs the format itself.
At some point somebody should rationalize this.  I suggest having
'stat' output the format itself, as that makes diagnosis easy and
intuitive.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Thu, 11 Nov 2010 22:05:01 GMT) Full text and rfc822 format available.

Message #116 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 7325 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>,
	Jim Meyering <jim <at> meyering.net>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Thu, 11 Nov 2010 22:09:17 +0000
On 11/11/10 17:54, Paul Eggert wrote:
> On 11/11/2010 07:24 AM, Eric Blake wrote:
>> %.0X as a mnemonic of 'show full precision but suppress
>> trailing zeros' kind of makes sense
> 
> I had considered supporting those semantics
> as well, which would have avoided all this business with
> fstimeprec.  That is, just trim trailing zeros, and don't
> worry about the file system time stamp resolution.  The problem
> with this approach is that different time stamps for the same
> file (atime, mtime, ctime) might show different numbers of digits,
> which might cause alignment problems and confusion.
> 
> I'm a bit leery of %.0X as meaning "show more than zero digits
> of precision", since .0 always means show zero everywhere else
> that printf-style formats are used.

Yes it's not ideal.

> I'm still not quite following the backward compatibility argument,
> as no matter what we do, we'll have different functionality than
> before.  %#.X outputs an integer time stamp with coreutils 5.97
> and outputs nothing with coreutils 8.6.  %.0X is the same as
> %#.X, so they're both equally "bad" in that respect.  %.*X outputs
> "*X" with 5.97 and "?X" with 8.6, so it's not portable either.

Yes 8.6 is special in this regard which is why
we're trying to release 8.7 quickly so as not
to have to worry about it.

> It's
> not a big deal, but I still mildly prefer the * notation.

Well I'm OK with %.0X %#.X or %.*X
so I've nothing more to add.

cheers,
Pádraig.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Fri, 12 Nov 2010 11:19:02 GMT) Full text and rfc822 format available.

Message #119 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, Eric Blake <eblake <at> redhat.com>,
	7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Fri, 12 Nov 2010 12:22:53 +0100
Pádraig Brady wrote:
> On 11/11/10 17:54, Paul Eggert wrote:
...
>> It's
>> not a big deal, but I still mildly prefer the * notation.

Same here.

However, here's an argument for using a different method, perhaps
with a hard-coded mapping from common FS types to known precision:

Running these two commands with different ordering prints
different results.  When the file with NS%10 == 0 comes first,
stat suppresses the trailing 0(s):

    $ stat -c '%4n %.*Z' 3 9
       3 1289555520.29981438
       9 1289555520.300814502

After the first non-multiple-of-10 nanoseconds value,
stat prints all trailing 0's:

    $ stat -c '%4n %.*Z' 9 3
       9 1289555520.300814502
       3 1289555520.299814380

It's easy to create files like that via e.g.,

  seq 10000|xargs touch -d '1970-01-01 18:43:33.5000000000'




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Fri, 12 Nov 2010 13:52:02 GMT) Full text and rfc822 format available.

Message #122 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, Eric Blake <eblake <at> redhat.com>,
	7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Fri, 12 Nov 2010 14:55:51 +0100
Pádraig Brady wrote:
>>>>> How about something like this instead?
>>>>>
>>>>>   %.X => precision is 9 (until POSIX goes sub-nanosecond :-)
>>>>>   %.5X => precision is 5
>>>>>   %.*X => precision determined by fstimeprec
>>>>>
>>>>> Then there's no reason for the "overrides" case.
>>>>
>>>> Good idea.  I prefer that.
>> ...
>>
>> Regardless, of syntax, can any of you suggest a good way to test this?
>> I can think of a few, but each has disadvantages.
>>
>>   - mount an ext2 file system and ensure that there are no nanoseconds
>>      Pro: works all the time, as long as ext2 is an option
>>      Con: root-only and requires mkfs.ext2
>>
>>      Code:
>>         dd if=/dev/zero of=blob count=2 seek=2M > /dev/null || skip=1
>>         mkdir mnt || skip=1
>>         mkfs -t ext2 -F blob \
>>           || skip_test_ "failed to create ext2 file system"
>>         mount -oloop blob mnt || skip=1

Insert "cd mnt", of course.

>>         touch -d '1970-01-01 18:43:33.5000000000' k || fail=1
>>         test "$(stat -c '%.*Y' k)" = 63813 || fail=1
>>
>>   - require a modern file system type and run a loop like this,
>>     hoping to find a time stamp with fewer than "normal" digits of
>>     nanosecond precision.
>>
>>       $ for i in $(seq 10); do rm -f k; touch -d '1970-01-01 18:43:33.5000000000' k; /cu/src/stat -c "%.*Y" k; done
>>       63813.500000000
>>       63813.50000000
>>       63813.500000000
>>       63813.500000000
>>       63813.500000000
>>       63813.50000000
>>       63813.500000000
>>       63813.500000000
>>       63813.500000000
>>       63813.500000000
>>
>>     Pro: does not require mount privileges
>>     Con: I suppose it may fail some of the time, no matter how many
>>          iterations we perform.
>>
>
> I prefer the latter.
> It's quick to run so do it 100 times
>
> require_nanosecond_fs_
>
> # Set this to avoid problems with weird time zones.
> TZ=UTC0
> export TZ
>
> # Use a time stamp near the Epoch to avoid trouble with leap seconds.
> touch -d '1970-01-01 18:43:33.5' k || framework_failure_
>
> prec=$(for i in $(seq 100); do
>          touch -a k; stat -c "%.*Y" k
>        done | cut -d. -f2 | wc -L)
> test "$prec" = 9 || fail=1

Thanks, but I'm dubious.
I ran 1000 iterations of something similar (wc -L computes max length.
min length would have worked).

touch -d '1970-01-01 18:43:33.5' k
for j in $(seq 1000); do
  printf "$j "
  for i in $(seq 100); do
    touch -a k
    stat -c "%.*Y" k
  done | grep -c -v '\.500000000$'
done |tee out

Here's the output.
Note that only on the 794'th iteration did I see the first (and only) 0.
At this point, I'm leaning towards using the root-only test.

iteration #-of-files-with-shortened-NS-count
###########
1 12
2 10
3 11
4 11
5 10
6 14
7 10
8 13
9 7
10 8
11 8
12 11
13 8
14 10
15 11
16 8
17 9
18 11
19 11
20 11
21 10
22 9
23 12
24 10
25 8
26 6
27 10
28 9
29 10
30 11
31 9
32 11
33 9
34 11
35 11
36 9
37 9
38 12
39 11
40 10
41 11
42 10
43 11
44 11
45 10
46 9
47 10
48 10
49 10
50 11
51 15
52 11
53 11
54 10
55 8
56 8
57 9
58 8
59 10
60 9
61 10
62 12
63 10
64 12
65 10
66 7
67 5
68 11
69 9
70 8
71 10
72 12
73 9
74 12
75 8
76 12
77 13
78 12
79 6
80 9
81 9
82 11
83 10
84 11
85 12
86 9
87 9
88 11
89 11
90 10
91 10
92 12
93 9
94 7
95 12
96 7
97 14
98 16
99 13
100 10
101 6
102 14
103 6
104 8
105 12
106 12
107 10
108 9
109 10
110 12
111 11
112 11
113 11
114 10
115 10
116 8
117 7
118 10
119 13
120 9
121 10
122 10
123 9
124 12
125 9
126 9
127 9
128 5
129 13
130 10
131 8
132 12
133 9
134 12
135 13
136 11
137 10
138 9
139 10
140 11
141 9
142 10
143 12
144 13
145 10
146 5
147 8
148 7
149 7
150 7
151 8
152 7
153 8
154 8
155 12
156 11
157 13
158 6
159 11
160 11
161 9
162 10
163 12
164 8
165 11
166 11
167 11
168 5
169 12
170 7
171 13
172 10
173 10
174 12
175 5
176 11
177 10
178 11
179 11
180 9
181 9
182 11
183 9
184 12
185 10
186 9
187 12
188 9
189 5
190 5
191 9
192 8
193 9
194 10
195 9
196 10
197 12
198 10
199 16
200 12
201 9
202 5
203 14
204 9
205 9
206 9
207 11
208 10
209 9
210 11
211 11
212 10
213 7
214 10
215 12
216 8
217 14
218 5
219 9
220 6
221 13
222 10
223 12
224 9
225 10
226 12
227 7
228 12
229 10
230 9
231 11
232 10
233 10
234 6
235 12
236 10
237 9
238 10
239 13
240 12
241 11
242 8
243 7
244 10
245 12
246 9
247 14
248 10
249 8
250 9
251 10
252 8
253 9
254 8
255 12
256 9
257 9
258 9
259 10
260 7
261 12
262 7
263 9
264 7
265 14
266 8
267 12
268 11
269 8
270 12
271 14
272 11
273 12
274 12
275 11
276 9
277 10
278 5
279 14
280 8
281 13
282 9
283 13
284 12
285 9
286 9
287 9
288 10
289 6
290 11
291 13
292 11
293 12
294 11
295 12
296 9
297 10
298 13
299 9
300 9
301 12
302 10
303 9
304 10
305 9
306 12
307 10
308 10
309 7
310 7
311 10
312 10
313 11
314 10
315 11
316 10
317 9
318 11
319 12
320 9
321 15
322 12
323 8
324 10
325 9
326 12
327 12
328 11
329 8
330 10
331 12
332 7
333 9
334 13
335 10
336 9
337 14
338 9
339 8
340 16
341 5
342 6
343 20
344 13
345 9
346 8
347 11
348 9
349 11
350 13
351 11
352 11
353 11
354 10
355 12
356 11
357 10
358 10
359 9
360 14
361 8
362 13
363 12
364 8
365 15
366 13
367 11
368 7
369 12
370 13
371 10
372 9
373 9
374 12
375 12
376 10
377 12
378 14
379 8
380 9
381 8
382 11
383 9
384 18
385 8
386 10
387 7
388 13
389 10
390 14
391 6
392 10
393 8
394 11
395 12
396 11
397 12
398 8
399 12
400 11
401 11
402 9
403 12
404 6
405 11
406 6
407 11
408 13
409 7
410 15
411 13
412 6
413 13
414 4
415 14
416 12
417 7
418 9
419 7
420 11
421 9
422 10
423 10
424 12
425 11
426 12
427 11
428 7
429 10
430 7
431 12
432 8
433 10
434 13
435 11
436 15
437 13
438 13
439 6
440 12
441 8
442 11
443 12
444 12
445 7
446 4
447 11
448 10
449 11
450 7
451 6
452 12
453 12
454 11
455 11
456 9
457 9
458 11
459 11
460 9
461 10
462 8
463 7
464 14
465 5
466 11
467 9
468 10
469 13
470 9
471 7
472 10
473 13
474 12
475 8
476 11
477 11
478 11
479 10
480 5
481 12
482 7
483 8
484 11
485 12
486 12
487 7
488 11
489 13
490 9
491 11
492 10
493 12
494 8
495 12
496 12
497 11
498 8
499 11
500 11
501 11
502 6
503 13
504 9
505 6
506 7
507 11
508 9
509 15
510 13
511 18
512 7
513 9
514 12
515 9
516 12
517 10
518 11
519 9
520 8
521 9
522 11
523 11
524 11
525 13
526 5
527 7
528 9
529 10
530 10
531 10
532 15
533 12
534 6
535 12
536 9
537 9
538 6
539 8
540 11
541 9
542 10
543 9
544 9
545 11
546 8
547 9
548 9
549 9
550 10
551 10
552 12
553 8
554 12
555 4
556 11
557 7
558 11
559 11
560 12
561 13
562 12
563 8
564 10
565 9
566 12
567 11
568 11
569 11
570 7
571 9
572 13
573 7
574 12
575 12
576 10
577 11
578 11
579 14
580 12
581 12
582 12
583 10
584 13
585 12
586 9
587 12
588 10
589 8
590 11
591 9
592 10
593 10
594 11
595 12
596 9
597 10
598 10
599 12
600 7
601 11
602 10
603 9
604 13
605 11
606 9
607 16
608 11
609 10
610 10
611 15
612 8
613 9
614 11
615 11
616 11
617 9
618 3
619 13
620 8
621 11
622 7
623 10
624 8
625 14
626 6
627 13
628 14
629 5
630 8
631 9
632 12
633 5
634 18
635 8
636 10
637 10
638 8
639 11
640 10
641 8
642 10
643 9
644 10
645 12
646 9
647 10
648 11
649 14
650 11
651 10
652 11
653 7
654 15
655 7
656 10
657 10
658 10
659 12
660 7
661 10
662 9
663 8
664 11
665 10
666 10
667 8
668 9
669 7
670 12
671 8
672 9
673 7
674 13
675 9
676 13
677 10
678 4
679 10
680 14
681 10
682 14
683 4
684 13
685 11
686 11
687 5
688 11
689 10
690 10
691 7
692 9
693 12
694 7
695 11
696 12
697 7
698 13
699 13
700 8
701 11
702 11
703 7
704 9
705 13
706 15
707 11
708 10
709 11
710 8
711 10
712 12
713 11
714 7
715 10
716 5
717 12
718 7
719 10
720 11
721 7
722 11
723 7
724 5
725 12
726 12
727 12
728 8
729 5
730 13
731 14
732 9
733 13
734 10
735 12
736 12
737 7
738 10
739 12
740 10
741 11
742 11
743 9
744 7
745 9
746 13
747 9
748 6
749 8
750 10
751 12
752 14
753 7
754 8
755 16
756 10
757 7
758 7
759 7
760 4
761 13
762 7
763 13
764 11
765 10
766 10
767 15
768 8
769 9
770 13
771 10
772 15
773 8
774 6
775 9
776 13
777 6
778 14
779 3
780 11
781 10
782 13
783 9
784 7
785 8
786 8
787 9
788 12
789 12
790 13
791 8
792 14
793 15
794 0
795 8
796 8
797 12
798 15
799 10
800 13
801 11
802 14
803 7
804 9
805 8
806 16
807 9
808 10
809 15
810 4
811 5
812 3
813 10
814 6
815 8
816 5
817 5
818 15
819 14
820 16
821 19
822 6
823 21
824 13
825 12
826 18
827 7
828 7
829 14
830 11
831 15
832 7
833 7
834 8
835 7
836 12
837 9
838 14
839 9
840 8
841 7
842 15
843 5
844 9
845 14
846 8
847 3
848 12
849 13
850 12
851 10
852 12
853 16
854 9
855 12
856 10
857 10
858 15
859 8
860 11
861 12
862 13
863 10
864 19
865 9
866 15
867 6
868 14
869 9
870 7
871 8
872 14
873 9
874 4
875 5
876 11
877 12
878 6
879 10
880 14
881 8
882 6
883 11
884 12
885 5
886 9
887 7
888 9
889 8
890 10
891 10
892 9
893 8
894 9
895 15
896 8
897 10
898 14
899 8
900 8
901 6
902 13
903 5
904 11
905 13
906 7
907 14
908 9
909 11
910 13
911 6
912 13
913 8
914 9
915 8
916 12
917 11
918 9
919 9
920 16
921 11
922 2
923 11
924 11
925 10
926 12
927 13
928 6
929 6
930 9
931 10
932 9
933 14
934 12
935 11
936 9
937 8
938 13
939 9
940 13
941 12
942 8
943 9
944 12
945 16
946 16
947 8
948 11
949 6
950 11
951 13
952 11
953 10
954 3
955 8
956 12
957 7
958 8
959 14
960 13
961 10
962 9
963 13
964 17
965 9
966 9
967 15
968 7
969 10
970 6
971 11
972 13
973 10
974 11
975 11
976 7
977 6
978 12
979 13
980 5
981 10
982 10
983 10
984 8
985 8
986 12
987 11
988 11
989 11
990 16
991 8
992 5
993 6
994 7
995 5
996 11
997 5
998 4
999 5
1000 7




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Fri, 12 Nov 2010 14:00:03 GMT) Full text and rfc822 format available.

Message #125 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Jim Meyering <jim <at> meyering.net>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, Eric Blake <eblake <at> redhat.com>,
	7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Fri, 12 Nov 2010 14:03:51 +0000
On 12/11/10 11:22, Jim Meyering wrote:
> Pádraig Brady wrote:
>> On 11/11/10 17:54, Paul Eggert wrote:
> ...
>>> It's
>>> not a big deal, but I still mildly prefer the * notation.
> 
> Same here.
> 
> However, here's an argument for using a different method, perhaps
> with a hard-coded mapping from common FS types to known precision:
> 
> Running these two commands with different ordering prints
> different results.  When the file with NS%10 == 0 comes first,
> stat suppresses the trailing 0(s):
> 
>     $ stat -c '%4n %.*Z' 3 9
>        3 1289555520.29981438
>        9 1289555520.300814502
> 
> After the first non-multiple-of-10 nanoseconds value,
> stat prints all trailing 0's:
> 
>     $ stat -c '%4n %.*Z' 9 3
>        9 1289555520.300814502
>        3 1289555520.299814380

That's just a special case of:
  find ... | xargs stat ...
So it's no worse that differences over multiple runs of stat IMHO

As for the general question of using hard coded resolutions for FS types.
It might be OK as long as you err'd on the side of too big rather than too small.
Though isn't everything going to tend towards nanoseconds going forward?

This feature is starting to seem a bit like over engineering
for what it gives us TBH.  If it was guaranteed to give us
an indication of the timestamp resolution, then OK
but otherwise I don't think it's worth it.

cheers,
Pádraig.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Fri, 12 Nov 2010 14:09:02 GMT) Full text and rfc822 format available.

Message #128 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Pádraig Brady <P <at> draigBrady.com>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, Eric Blake <eblake <at> redhat.com>,
	7325 <at> debbugs.gnu.org
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Fri, 12 Nov 2010 15:12:51 +0100
Pádraig Brady wrote:

> On 12/11/10 11:22, Jim Meyering wrote:
>> Pádraig Brady wrote:
>>> On 11/11/10 17:54, Paul Eggert wrote:
>> ...
>>>> It's
>>>> not a big deal, but I still mildly prefer the * notation.
>>
>> Same here.
>>
>> However, here's an argument for using a different method, perhaps
>> with a hard-coded mapping from common FS types to known precision:
>>
>> Running these two commands with different ordering prints
>> different results.  When the file with NS%10 == 0 comes first,
>> stat suppresses the trailing 0(s):
>>
>>     $ stat -c '%4n %.*Z' 3 9
>>        3 1289555520.29981438
>>        9 1289555520.300814502
>>
>> After the first non-multiple-of-10 nanoseconds value,
>> stat prints all trailing 0's:
>>
>>     $ stat -c '%4n %.*Z' 9 3
>>        9 1289555520.300814502
>>        3 1289555520.299814380
>
> That's just a special case of:
>   find ... | xargs stat ...
> So it's no worse that differences over multiple runs of stat IMHO
>
> As for the general question of using hard coded resolutions for FS types.
> It might be OK as long as you err'd on the side of too big rather than too small.
> Though isn't everything going to tend towards nanoseconds going forward?
>
> This feature is starting to seem a bit like over engineering
> for what it gives us TBH.  If it was guaranteed to give us
> an indication of the timestamp resolution, then OK
> but otherwise I don't think it's worth it.

I agree.
I'd like to defer the addition of this feature,
at least until it's more predictable.

Is that ok with you, Paul?




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Fri, 12 Nov 2010 19:20:03 GMT) Full text and rfc822 format available.

Message #131 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Jim Meyering <jim <at> meyering.net>
Cc: Eric Blake <eblake <at> redhat.com>, 7325 <at> debbugs.gnu.org,
	Pádraig Brady <P <at> draigBrady.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Fri, 12 Nov 2010 11:24:19 -0800
On 11/12/2010 06:12 AM, Jim Meyering wrote:
> I'd like to defer the addition of this feature,
> at least until it's more predictable.
> 
> Is that ok with you, Paul?

Doesn't bother me.  We can revisit this again in twenty years.
Perhaps by then, pathconf will support interrogation of
file systems for their time stamp resolutions, as POSIX requires.

In the meantime we can add it to 'diff' instead, where it
wouldn't be as problematic.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Sat, 13 Nov 2010 10:41:02 GMT) Full text and rfc822 format available.

Message #134 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: Eric Blake <eblake <at> redhat.com>, 7325 <at> debbugs.gnu.org,
	Pádraig Brady <P <at> draigBrady.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Sat, 13 Nov 2010 11:45:09 +0100
Paul Eggert wrote:
> On 11/12/2010 06:12 AM, Jim Meyering wrote:
>> I'd like to defer the addition of this feature,
>> at least until it's more predictable.
>>
>> Is that ok with you, Paul?
>
> Doesn't bother me.  We can revisit this again in twenty years.
> Perhaps by then, pathconf will support interrogation of
> file systems for their time stamp resolutions, as POSIX requires.
>
> In the meantime we can add it to 'diff' instead, where it
> wouldn't be as problematic.

Here's what I'm planning.
With this, I'm ready for coreutils-8.7.
Debating whether to make another snapshot first.  We'll see...

From 4a8e9bf14c33b356680298d29f7321d82d4fde5d Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering <at> redhat.com>
Date: Sat, 13 Nov 2010 08:02:02 +0100
Subject: [PATCH 1/3] stat: do not provide variable precision time stamps

* src/stat.c: Don't include fstimeprec.c.
(out_epoch_sec): Don't call fstimeprec.
* NEWS: Update description.
* doc/coreutils.texi: Likewise.
---
 NEWS               |    5 +++--
 doc/coreutils.texi |   10 +++++-----
 gnulib             |    2 +-
 src/stat.c         |    6 +-----
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/NEWS b/NEWS
index e77768d..51e0650 100644
--- a/NEWS
+++ b/NEWS
@@ -24,8 +24,9 @@ GNU coreutils NEWS                                    -*- outline -*-
   stat's %X, %Y, and %Z directives once again print only the integer
   part of seconds since the epoch.  This reverts a change from
   coreutils-8.6, that was deemed unnecessarily disruptive.  To obtain
-  a full resolution time stamp for %X, use %.X; if you want (say) just
-  3 fractional digits, use %.3X.  Likewise for %Y and %Z.
+  a nanosecond-precision floating point time stamp for %X use %.X;
+  if you want (say) just 3 fractional digits, use %.3X.  Likewise
+  for %Y and %Z.

   stat's new %W format directive would print floating point seconds.
   However, with the above change to %X, %Y and %Z, we've made %W work
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index ce56b0e..6a4257f 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -10718,10 +10718,10 @@ stat invocation

 The @samp{%W}, @samp{%X}, @samp{%Y}, and @samp{%Z} formats accept a
 precision preceded by a period to specify the number of digits to
-print after the decimal point. For example, @samp{%.9X} outputs the
-last access time to nanosecond precision.  If a period is given but no
-precision, @command{stat} uses the estimated precision of the file
-system. When discarding excess precision, time stamps are truncated
+print after the decimal point.  For example, @samp{%.3X} outputs the
+last access time to millisecond precision.  If a period is given but no
+precision, @command{stat} uses 9 digits, so @samp{%.X} is equivalent to
+@samp{%.9X}  When discarding excess precision, time stamps are truncated
 toward minus infinity.

 @example
@@ -10737,7 +10737,7 @@ stat invocation
   $ stat -c '[%.3Y]' /usr
   [1288929712.114]
   $ stat -c '[%.Y]' /usr
-  [1288929712.114951]
+  [1288929712.114951834]
 @end example

 The mount point printed by @samp{%m} is similar to that output
diff --git a/gnulib b/gnulib
index 4baf5c1..6383a3b 160000
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit 4baf5c1e594a65a315fbd5094eaeeb11f4630d18
+Subproject commit 6383a3bbe16d3615791568c030fed5bfe86a4381
diff --git a/src/stat.c b/src/stat.c
index ae7ce02..b419f19 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -63,7 +63,6 @@
 #include "file-type.h"
 #include "filemode.h"
 #include "fs.h"
-#include "fstimeprec.h"
 #include "getopt.h"
 #include "mountlist.h"
 #include "quote.h"
@@ -557,10 +556,7 @@ out_epoch_sec (char *pformat, size_t prefix_len, struct stat const *statbuf,
         }
       else
         {
-          static struct fstimeprec *tab;
-          if (! tab)
-            tab = fstimeprec_alloc ();
-          precision = fstimeprec (tab, statbuf);
+          precision = 9;
         }

       if (precision && ISDIGIT (dot[-1]))
--
1.7.3.2.4.g60aa9


From ff5fc553f974513e27015faa414fca3603e928e7 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering <at> redhat.com>
Date: Sat, 13 Nov 2010 08:04:13 +0100
Subject: [PATCH 2/3] maint: remove fstimeprec (variable precision time stamp) support

The implementation of variable-precision time stamps relied
on heuristics that made the output subtly nondeterministic,
or at least hard to reproduce:
http://thread.gmane.org/gmane.comp.gnu.coreutils.bugs/21531/focus=21538
So, for now at least, we're removing that feature.
* bootstrap.conf (gnulib_modules): Remove fstimeprec.
* gl/lib/fstimeprec.c, gl/lib/fstimeprec.h: Remove files.
* gl/modules/fstimeprec, gl/modules/fstimeprec-tests: Likewise.
* gl/tests/test-fstimeprec.c: Remove file.
---
 bootstrap.conf              |    1 -
 gl/lib/fstimeprec.c         |  178 -------------------------------------------
 gl/lib/fstimeprec.h         |   22 -----
 gl/modules/fstimeprec       |   24 ------
 gl/modules/fstimeprec-tests |   10 ---
 gl/tests/test-fstimeprec.c  |   74 ------------------
 6 files changed, 0 insertions(+), 309 deletions(-)
 delete mode 100644 gl/lib/fstimeprec.c
 delete mode 100644 gl/lib/fstimeprec.h
 delete mode 100644 gl/modules/fstimeprec
 delete mode 100644 gl/modules/fstimeprec-tests
 delete mode 100644 gl/tests/test-fstimeprec.c

diff --git a/bootstrap.conf b/bootstrap.conf
index 5a6ebae..18ef914 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -85,7 +85,6 @@ gnulib_modules="
   freopen
   freopen-safer
   fseeko
-  fstimeprec
   fsusage
   fsync
   ftello
diff --git a/gl/lib/fstimeprec.c b/gl/lib/fstimeprec.c
deleted file mode 100644
index fd63054..0000000
--- a/gl/lib/fstimeprec.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/* Determine a file system's time stamp precision.
-
-   Copyright 2010 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* written by Paul Eggert */
-
-#include <config.h>
-#include "fstimeprec.h"
-
-#include "hash.h"
-#include "stat-time.h"
-#include <limits.h>
-#include <stdlib.h>
-
-/* A hash table that maps device numbers to precisions.  */
-struct fstimeprec
-{
-  /* Map device numbers to precisions.  */
-  struct hash_table *map;
-
-  /* Cache of the most recently allocated and otherwise-unused storage
-     for probing this table.  */
-  struct ent *probe;
-};
-
-/* A pair that maps a device number to a precision.  */
-struct ent
-{
-  dev_t dev;
-  int prec;
-};
-
-/* Hash an entry.  */
-static size_t
-ent_hash (void const *x, size_t table_size)
-{
-  struct ent const *p = x;
-  dev_t dev = p->dev;
-
-  /* FIXME: This code is duplicated from di-set.c.  */
-  /* When DEV is wider than size_t, exclusive-OR the words of DEV into H.
-     This avoids loss of info, without applying % to the wider type,
-     which could be quite slow on some systems.  */
-  size_t h = dev;
-  unsigned int i;
-  unsigned int n_words = sizeof dev / sizeof h + (sizeof dev % sizeof h != 0);
-  for (i = 1; i < n_words; i++)
-    h ^= dev >> CHAR_BIT * sizeof h * i;
-
-  return h % table_size;
-}
-
-/* Return true if two entries are the same.  */
-static bool
-ent_compare (void const *x, void const *y)
-{
-  struct ent const *a = x;
-  struct ent const *b = y;
-  return a->dev == b->dev;
-}
-
-/* Using the SET table, map a device to an entry that represents
-   the file system precision.  Return NULL on error.  */
-static struct ent *
-map_device (struct fstimeprec *tab, dev_t dev)
-{
-  /* Find space for the probe, reusing the cache if available.  */
-  struct ent *ent;
-  struct ent *probe = tab->probe;
-  if (probe)
-    {
-      /* If repeating a recent query, return the cached result.   */
-      if (probe->dev == dev)
-        return probe;
-    }
-  else
-    {
-      tab->probe = probe = malloc (sizeof *probe);
-      if (! probe)
-        return NULL;
-      probe->prec = 0;
-    }
-
-  /* Probe for the device.  */
-  probe->dev = dev;
-  ent = hash_insert (tab->map, probe);
-  if (ent == probe)
-    tab->probe = NULL;
-  return ent;
-}
-
-/* Return a newly allocated table of file system time stamp
-   resolutions, or NULL if out of memory.  */
-struct fstimeprec *
-fstimeprec_alloc (void)
-{
-  struct fstimeprec *tab = malloc (sizeof *tab);
-  if (tab)
-    {
-      enum { INITIAL_DEV_MAP_SIZE = 11 };
-      tab->map = hash_initialize (INITIAL_DEV_MAP_SIZE, NULL,
-                                  ent_hash, ent_compare, free);
-      if (! tab->map)
-        {
-          free (tab);
-          return NULL;
-        }
-      tab->probe = NULL;
-    }
-  return tab;
-}
-
-/* Free TAB.  */
-void
-fstimeprec_free (struct fstimeprec *tab)
-{
-  hash_free (tab->map);
-  free (tab->probe);
-  free (tab);
-}
-
-/* Using the cached information in TAB, return the estimated precision
-   of time stamps for the file system containing the file whose status
-   info is in ST.  The returned value counts the number of decimal
-   fraction digits.  Return 0 on failure.
-
-   If TAB is null, the guess is based purely on ST.  */
-int
-fstimeprec (struct fstimeprec *tab, struct stat const *st)
-{
-  /* Map the device number to an entry.  */
-  struct ent *ent = (tab ? map_device (tab, st->st_dev) : NULL);
-
-  /* Guess the precision based on what has been seen so far.  */
-  int prec = (ent ? ent->prec : 0);
-
-  /* If the current file's timestamp resolution is higher than the
-     guess, increase the guess.  */
-  if (prec < 9)
-    {
-      struct timespec ats = get_stat_atime (st);
-      struct timespec mts = get_stat_mtime (st);
-      struct timespec cts = get_stat_ctime (st);
-      struct timespec bts = get_stat_birthtime (st);
-      unsigned int ans = ats.tv_nsec;
-      unsigned int mns = mts.tv_nsec;
-      unsigned int cns = cts.tv_nsec;
-      unsigned int bns = bts.tv_nsec < 0 ? 0 : bts.tv_nsec;
-      unsigned int power = 10;
-      int p;
-      for (p = prec + 1; p < 9; p++)
-        power *= 10;
-
-      while (ans % power | mns % power | cns % power | bns % power)
-        {
-          power /= 10;
-          prec++;
-        }
-
-      if (ent)
-        ent->prec = prec;
-    }
-
-  return prec;
-}
diff --git a/gl/lib/fstimeprec.h b/gl/lib/fstimeprec.h
deleted file mode 100644
index 8ec24df..0000000
--- a/gl/lib/fstimeprec.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <sys/stat.h>
-
-#ifndef ATTRIBUTE_MALLOC
-# if __GNUC__ >= 3
-#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
-# else
-#  define ATTRIBUTE_MALLOC
-# endif
-#endif
-
-#ifndef _GL_ARG_NONNULL
-# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3
-#  define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params))
-# else
-#  define _GL_ARG_NONNULL(params)
-# endif
-#endif
-
-struct fstimeprec *fstimeprec_alloc (void) ATTRIBUTE_MALLOC;
-void fstimeprec_free (struct fstimeprec *) _GL_ARG_NONNULL ((1));
-int fstimeprec (struct fstimeprec *, struct stat const *)
-  _GL_ARG_NONNULL ((2));
diff --git a/gl/modules/fstimeprec b/gl/modules/fstimeprec
deleted file mode 100644
index 787c2e7..0000000
--- a/gl/modules/fstimeprec
+++ /dev/null
@@ -1,24 +0,0 @@
-Description:
-estimate precision of time stamps in file systems
-
-Files:
-lib/fstimeprec.c
-lib/fstimeprec.h
-
-Depends-on:
-hash
-stat-time
-
-configure.ac:
-
-Makefile.am:
-lib_SOURCES += fstimeprec.c fstimeprec.h
-
-Include:
-"fstimeprec.h"
-
-License
-GPL
-
-Maintainer:
-Paul Eggert and Jim Meyering
diff --git a/gl/modules/fstimeprec-tests b/gl/modules/fstimeprec-tests
deleted file mode 100644
index bf6b49e..0000000
--- a/gl/modules/fstimeprec-tests
+++ /dev/null
@@ -1,10 +0,0 @@
-Files:
-tests/test-fstimeprec.c
-
-Depends-on:
-
-configure.ac:
-
-Makefile.am:
-TESTS += test-fstimeprec
-check_PROGRAMS += test-fstimeprec
diff --git a/gl/tests/test-fstimeprec.c b/gl/tests/test-fstimeprec.c
deleted file mode 100644
index f699139..0000000
--- a/gl/tests/test-fstimeprec.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Test the fstimeprec module.
-   Copyright (C) 2010 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* written by Paul Eggert */
-
-#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/stat.h>
-
-#define ASSERT(expr) \
-  do                                                                         \
-    {                                                                        \
-      if (!(expr))                                                           \
-        {                                                                    \
-          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
-          fflush (stderr);                                                   \
-          abort ();                                                          \
-        }                                                                    \
-    }                                                                        \
-  while (0)
-
-#include "fstimeprec.h"
-
-static int
-fstimeprec_file (struct fstimeprec *tab, char const *file)
-{
-  struct stat st;
-  if (stat (file, &st) != 0)
-    return 0;
-  return fstimeprec (tab, &st);
-}
-
-int
-main (void)
-{
-  struct fstimeprec *tab = fstimeprec_alloc ();
-  ASSERT (tab);
-
-  int m1 = fstimeprec_file (tab, "/");
-  int m2 = fstimeprec_file (tab, ".");
-  int m3 = fstimeprec_file (tab, "..");
-  ASSERT (0 <= m1 && m1 <= 9);
-  ASSERT (0 <= m2 && m2 <= 9);
-  ASSERT (0 <= m3 && m3 <= 9);
-
-  int n1 = fstimeprec_file (tab, "/");
-  int n2 = fstimeprec_file (tab, ".");
-  int n3 = fstimeprec_file (tab, "..");
-  ASSERT (0 <= n1 && n1 <= 9);
-  ASSERT (0 <= n2 && n2 <= 9);
-  ASSERT (0 <= n3 && n3 <= 9);
-
-  ASSERT (m1 <= n1);
-  ASSERT (m2 <= n2);
-  ASSERT (m3 <= n3);
-
-  fstimeprec_free (tab);
-
-  return 0;
-}
--
1.7.3.2.4.g60aa9


From 2d5b3329a2c97a2fee4851d9551ee3d080106765 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering <at> redhat.com>
Date: Sat, 13 Nov 2010 10:12:49 +0100
Subject: [PATCH 3/3] build: update gnulib for linux 2.6.9 nanosleep workaround

Also, do the following to avoid "make syntax-check" failure
induced by new rules.
* .x-sc_bindtextdomain: Exempt files with an #ifdef'd "main".
* Makefile.am: Add this file.
---
 .x-sc_bindtextdomain |    7 +++++++
 Makefile.am          |    1 +
 2 files changed, 8 insertions(+), 0 deletions(-)
 create mode 100644 .x-sc_bindtextdomain

diff --git a/.x-sc_bindtextdomain b/.x-sc_bindtextdomain
new file mode 100644
index 0000000..2a568be
--- /dev/null
+++ b/.x-sc_bindtextdomain
@@ -0,0 +1,7 @@
+^gl/lib/randint\.c$
+^gl/tests/test-di-set\.c$
+^gl/tests/test-fadvise\.c$
+^gl/tests/test-ino-map\.c$
+^gl/tests/test-mbsalign\.c$
+^gl/tests/test-rand-isaac\.c$
+^lib/euidaccess-stat\.c$
diff --git a/Makefile.am b/Makefile.am
index 9fd5361..b61229d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,6 +41,7 @@ changelog_etc =				\

 syntax_check_exceptions =		\
   .x-sc_GPL_version			\
+  .x-sc_bindtextdomain			\
   .x-sc_error_message_uppercase		\
   .x-sc_file_system			\
   .x-sc_obsolete_symbols		\
--
1.7.3.2.4.g60aa9




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Sat, 13 Nov 2010 17:57:01 GMT) Full text and rfc822 format available.

Message #137 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Jim Meyering <jim <at> meyering.net>
Cc: Eric Blake <eblake <at> redhat.com>, 7325 <at> debbugs.gnu.org,
	Pádraig Brady <P <at> draigBrady.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Sat, 13 Nov 2010 10:01:21 -0800
On 11/13/2010 02:45 AM, Jim Meyering wrote:

> Here's what I'm planning.

Looks good, thanks, except for NEWS:

> +  a nanosecond-precision floating point time stamp for %X use %.X;

It's fixed-point, not floating point, so I'd remove "floating point".

And in coreutils.texi:

> +precision, @command{stat} uses 9 digits, so @samp{%.X} is equivalent to
> +@samp{%.9X}  When discarding excess precision, time stamps are truncated

There's a period missing after the "@samp{%.9X}" (though ideally the sentence
would be reworded so as to avoid the need for any period after the sample,
as the "%.9X." looks bad when it's printed).




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Sat, 13 Nov 2010 17:59:01 GMT) Full text and rfc822 format available.

Message #140 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: Eric Blake <eblake <at> redhat.com>, 7325 <at> debbugs.gnu.org,
	Pádraig Brady <P <at> draigBrady.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Sat, 13 Nov 2010 19:03:30 +0100
Paul Eggert wrote:

> On 11/13/2010 02:45 AM, Jim Meyering wrote:
>
>> Here's what I'm planning.
>
> Looks good, thanks, except for NEWS:
>
>> +  a nanosecond-precision floating point time stamp for %X use %.X;
>
> It's fixed-point, not floating point, so I'd remove "floating point".
>
> And in coreutils.texi:
>
>> +precision, @command{stat} uses 9 digits, so @samp{%.X} is equivalent to
>> +@samp{%.9X}  When discarding excess precision, time stamps are truncated
>
> There's a period missing after the "@samp{%.9X}" (though ideally the sentence
> would be reworded so as to avoid the need for any period after the sample,
> as the "%.9X." looks bad when it's printed).

Thanks.  Unfortunately, I received this about 20 minutes
too late to make those changes for the release.




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Sat, 13 Nov 2010 21:00:03 GMT) Full text and rfc822 format available.

Message #143 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Jim Meyering <jim <at> meyering.net>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: Eric Blake <eblake <at> redhat.com>, 7325 <at> debbugs.gnu.org,
	Pádraig Brady <P <at> draigBrady.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Sat, 13 Nov 2010 22:04:31 +0100
Paul Eggert wrote:

> On 11/13/2010 02:45 AM, Jim Meyering wrote:
>
>> Here's what I'm planning.
>
> Looks good, thanks, except for NEWS:
>
>> +  a nanosecond-precision floating point time stamp for %X use %.X;
>
> It's fixed-point, not floating point, so I'd remove "floating point".
>
> And in coreutils.texi:
>
>> +precision, @command{stat} uses 9 digits, so @samp{%.X} is equivalent to
>> +@samp{%.9X}  When discarding excess precision, time stamps are truncated
>
> There's a period missing after the "@samp{%.9X}" (though ideally the sentence
> would be reworded so as to avoid the need for any period after the sample,
> as the "%.9X." looks bad when it's printed).

"%.9X". doesn't look that bad to me (neither in .info nor in .pdf)
How's this, Paul?

From f70c7b785b93dd436788d34827b209453157a6f2 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert <at> cs.ucla.edu>
Date: Sat, 13 Nov 2010 22:02:29 +0100
Subject: [PATCH] doc: tweak NEWS and coreutils.texi

* doc/coreutils.texi (stat invocation): Add sentence-ending period.
* NEWS: Correct stat change description: s/floating point //.
* cfg.mk (old_NEWS_hash): Update, to match this NEWS change.
---
 NEWS               |    8 ++++----
 cfg.mk             |    2 +-
 doc/coreutils.texi |    2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/NEWS b/NEWS
index a40a0aa..1da7db2 100644
--- a/NEWS
+++ b/NEWS
@@ -26,10 +26,10 @@ GNU coreutils NEWS                                    -*- outline -*-

   stat's %X, %Y, and %Z directives once again print only the integer
   part of seconds since the epoch.  This reverts a change from
-  coreutils-8.6, that was deemed unnecessarily disruptive.  To obtain
-  a nanosecond-precision floating point time stamp for %X use %.X;
-  if you want (say) just 3 fractional digits, use %.3X.  Likewise
-  for %Y and %Z.
+  coreutils-8.6, that was deemed unnecessarily disruptive.
+  To obtain a nanosecond-precision time stamp for %X use %.X;
+  if you want (say) just 3 fractional digits, use %.3X.
+  Likewise for %Y and %Z.

   stat's new %W format directive would print floating point seconds.
   However, with the above change to %X, %Y and %Z, we've made %W work
diff --git a/cfg.mk b/cfg.mk
index 244358c..7651ab2 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -27,7 +27,7 @@ bootstrap-tools = autoconf,automake,gnulib,bison
 # Now that we have better tests, make this the default.
 export VERBOSE = yes

-old_NEWS_hash = 24f3cbd2c625a297dc4cfb1b076eeaae
+old_NEWS_hash = e2a254a0d4c81397994ea10a15663ac3

 # Add an exemption for sc_makefile_at_at_check.
 _makefile_at_at_check_exceptions = ' && !/^cu_install_program =/'
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 6a4257f..1373f94 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -10721,7 +10721,7 @@ stat invocation
 print after the decimal point.  For example, @samp{%.3X} outputs the
 last access time to millisecond precision.  If a period is given but no
 precision, @command{stat} uses 9 digits, so @samp{%.X} is equivalent to
-@samp{%.9X}  When discarding excess precision, time stamps are truncated
+@samp{%.9X}.  When discarding excess precision, time stamps are truncated
 toward minus infinity.

 @example
--
1.7.3.2.4.g60aa9




Information forwarded to owner <at> debbugs.gnu.org, bug-coreutils <at> gnu.org:
bug#7325; Package coreutils. (Sun, 14 Nov 2010 03:05:02 GMT) Full text and rfc822 format available.

Message #146 received at 7325 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Jim Meyering <jim <at> meyering.net>
Cc: Eric Blake <eblake <at> redhat.com>, 7325 <at> debbugs.gnu.org,
	Pádraig Brady <P <at> draigBrady.com>
Subject: Re: bug#7325: new test failure due to non-portability of printf
	formats like %05.3s
Date: Sat, 13 Nov 2010 19:09:48 -0800
On 11/13/2010 01:04 PM, Jim Meyering wrote:
> "%.9X". doesn't look that bad to me (neither in .info nor in .pdf)
> How's this, Paul?

Hmm, sorry, I just assumed that it would look bad, but if it looks OK
to you then that's fine.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sun, 12 Dec 2010 12:24:04 GMT) Full text and rfc822 format available.

This bug report was last modified 14 years and 191 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.