Re: [coreutils] stat: reverting recent %X %Y %Z change

2010-10-22 Thread Pádraig Brady
On 22/10/10 18:43, Jim Meyering wrote:
> Part of reverting this change:
> 
> stat now outputs the full sub-second resolution for the atime,
> mtime, and ctime values since the Epoch, when using the %X, %Y, and
> %Z directives of the --format option.  This matches the fact that
> %x, %y, and %z were already doing so for the human-readable variant.
> 
> means considering whether to do the same sort of thing with the
> newly-added %W (birth time/crtime).  Note that %W currently expands to "-"
> on systems with no support (e.g., linux).
> 
> I don't particularly like the idea of making stat do this:
> 
> $ src/stat -c %W.%:W .
> -.-
> 
> Rather, I have a slight preference to make it do this:
> 
> $ src/stat -c %W.%:W .
> 0.0

I prefer that as it would mean less special
cases in code that uses the output.

> In any case, I think %w should still expand to "-".
> 
> The alternative is to leave %W separate, with no %:W variant.
> I.e., %W would continue to print floating point seconds.
> In that case, it would be inconsistent with %X, %Y and %Z.

I don't like that.

cheers,
Pádraig.



Re: [coreutils] stat: reverting recent %X %Y %Z change

2010-10-23 Thread Jim Meyering
Pádraig Brady wrote:
> On 22/10/10 18:43, Jim Meyering wrote:
>> Part of reverting this change:
>>
>> stat now outputs the full sub-second resolution for the atime,
>> mtime, and ctime values since the Epoch, when using the %X, %Y, and
>> %Z directives of the --format option.  This matches the fact that
>> %x, %y, and %z were already doing so for the human-readable variant.
>>
>> means considering whether to do the same sort of thing with the
>> newly-added %W (birth time/crtime).  Note that %W currently expands to "-"
>> on systems with no support (e.g., linux).
>>
>> I don't particularly like the idea of making stat do this:
>>
>> $ src/stat -c %W.%:W .
>> -.-
>>
>> Rather, I have a slight preference to make it do this:
>>
>> $ src/stat -c %W.%:W .
>> 0.0
>
> I prefer that as it would mean less special
> cases in code that uses the output.

Exactly.

>> In any case, I think %w should still expand to "-".
>>
>> The alternative is to leave %W separate, with no %:W variant.
>> I.e., %W would continue to print floating point seconds.
>> In that case, it would be inconsistent with %X, %Y and %Z.
>
> I don't like that.

Thanks for the feedback!



Re: [coreutils] stat: reverting recent %X %Y %Z change

2010-10-24 Thread Jim Meyering
Jim Meyering wrote:

> Pádraig Brady wrote:
>> On 22/10/10 18:43, Jim Meyering wrote:
>>> Part of reverting this change:
>>>
>>> stat now outputs the full sub-second resolution for the atime,
>>> mtime, and ctime values since the Epoch, when using the %X, %Y, and
>>> %Z directives of the --format option.  This matches the fact that
>>> %x, %y, and %z were already doing so for the human-readable variant.
>>>
>>> means considering whether to do the same sort of thing with the
>>> newly-added %W (birth time/crtime).  Note that %W currently expands to "-"
>>> on systems with no support (e.g., linux).
>>>
>>> I don't particularly like the idea of making stat do this:
>>>
>>> $ src/stat -c %W.%:W .
>>> -.-
>>>
>>> Rather, I have a slight preference to make it do this:
>>>
>>> $ src/stat -c %W.%:W .
>>> 0.0
>>
>> I prefer that as it would mean less special
>> cases in code that uses the output.
>
> Exactly.
>
>>> In any case, I think %w should still expand to "-".
>>>
>>> The alternative is to leave %W separate, with no %:W variant.
>>> I.e., %W would continue to print floating point seconds.
>>> In that case, it would be inconsistent with %X, %Y and %Z.
>>
>> I don't like that.
>
> Thanks for the feedback!

Here's a mostly-ready proposed change.

I've just realized it doesn't mention the nanosecond field width issue:
the default is 9, and it's always zero-padded, but only to a width of 9,
which is surprising if you ever specify a larger field width:

$ src/stat -c %12:W .
   0

I dislike such surprises...

I should probably add a few tests, too.


>From d9d07d63f18e3482432fe458e3f7dd421bf51ef0 Mon Sep 17 00:00:00 2001
From: Jim Meyering 
Date: Thu, 21 Oct 2010 18:41:24 +0200
Subject: [PATCH] stat: revert change to %X, %Y, %Z; use %:X to print fractional 
seconds

This reverts part of the recent commit 9069af45,
"stat: print timestamps to full resolution".  We prefer to retain
portability of %X, %Y and %Z uses, while still providing access to
full-resolution time stamps.
* src/stat.c (print_it): Accept a new %...:[XYZ] format directive,
e.g., %:X, to print the nanoseconds portion of the corresponding time.
For example, %3.3:Y prints the zero-padded, truncated, milliseconds
part of the time of last modification.
(print_it): Update print_func signature to match.
(neg_to_zero): New helper function.
(epoch_time): Remove function; replace with...
(epoch_sec): New function; use timetostr.
(epoch_ns): New function.
(print_statfs): Change type of "m" to unsigned int,
now that it must accommodate values larger than 255.
(print_stat): Likewise.
Map :X to a code of 'X' + 256.  Likewise for Y, Z and W.
(usage): Update.
* tests/touch/60-seconds: Use %Y.%:Y in place of %Y.
* NEWS (Changes in behavior): Mention this.
Thanks to Andreas Schwab for raising the issue.
---
 NEWS   |   15 ++
 doc/coreutils.texi |6 ++-
 src/stat.c |  112 +++
 tests/touch/60-seconds |2 +-
 4 files changed, 95 insertions(+), 40 deletions(-)

diff --git a/NEWS b/NEWS
index f28c243..09b7225 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,21 @@ GNU coreutils NEWS-*- 
outline -*-

 * Noteworthy changes in release ?.? (-??-??) [?]

+** Changes in behavior
+
+  stat's %X, %Y, and %Z directives once again print only the integer
+  part of seconds since the epoch.  This reverts a change, introduced
+  in 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.
+
+  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.
+

 * Noteworthy changes in release 8.6 (2010-10-15) [stable]

diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 4d17ed1..94e8ebf 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -10698,13 +10698,17 @@ stat invocation
 @item %u - User ID of owner
 @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{-}
+...@item %W - Time of file birth as seconds since Epoch, or @samp{0}
+...@item %:W - Time of file birth: 0-padded 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: 0-padded nanoseconds remainder
 @item %y - Time of last modification
 @item %Y - Time of last modification as seconds since Epoch
+...@item %:Y - Time of last modification: 0-padded nanoseconds remainder
 @item %z - Time of last 

Re: [coreutils] stat: reverting recent %X %Y %Z change

2010-10-26 Thread Jim Meyering
Jim Meyering wrote:
> Jim Meyering wrote:
>
>> Pádraig Brady wrote:
>>> On 22/10/10 18:43, Jim Meyering wrote:
 Part of reverting this change:

 stat now outputs the full sub-second resolution for the atime,
 mtime, and ctime values since the Epoch, when using the %X, %Y, and
 %Z directives of the --format option.  This matches the fact that
 %x, %y, and %z were already doing so for the human-readable variant.

 means considering whether to do the same sort of thing with the
 newly-added %W (birth time/crtime).  Note that %W currently expands to "-"
 on systems with no support (e.g., linux).

 I don't particularly like the idea of making stat do this:

 $ src/stat -c %W.%:W .
 -.-

 Rather, I have a slight preference to make it do this:

 $ src/stat -c %W.%:W .
 0.0
>>>
>>> I prefer that as it would mean less special
>>> cases in code that uses the output.
>>
>> Exactly.
>>
 In any case, I think %w should still expand to "-".

 The alternative is to leave %W separate, with no %:W variant.
 I.e., %W would continue to print floating point seconds.
 In that case, it would be inconsistent with %X, %Y and %Z.
>>>
>>> I don't like that.
>>
>> Thanks for the feedback!
>
> Here's a mostly-ready proposed change.
>
> I've just realized it doesn't mention the nanosecond field width issue:
> the default is 9, and it's always zero-padded, but only to a width of 9,
> which is surprising if you ever specify a larger field width:
>
> $ src/stat -c %12:W .
>0
>
> I dislike such surprises...

I've adjusted things so that it's not so bad.

Setup:

$ touch -d '2010-10-21 18:43:33.00789' k

With the incremental patch below, you get "09" modifiers only
when you specify no other modifier:

$ stat -c ns_%12:X_ k
ns_ 789_
$ stat -c ns_%:X_ k
ns_00789_
$ stat -c ns_%9:X_ k
ns_  789_

diff --git a/src/stat.c b/src/stat.c
index 9a6bb8f..9d3db1b 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -471,14 +471,19 @@ epoch_sec (struct timespec t)
   return timetostr (t.tv_sec, str);
 }

-/* Return a string representation (in static storage)
-   of nanoseconds part of T.  */
-static char * ATTRIBUTE_WARN_UNUSED_RESULT
-epoch_ns (struct timespec t)
+/* Output the number of nanoseconds, ARG.tv_nsec.  */
+static void
+out_ns (char *pformat, size_t prefix_len, struct timespec arg)
 {
-  static char str[10];
-  sprintf (str, "%09ld", t.tv_nsec);
-  return str;
+  /* 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 off by a factor of 10 or more.  */
+  strcpy (pformat + prefix_len, prefix_len == 1 ? "09ld" : "ld");
+  printf (pformat, arg.tv_nsec);
 }

 static void
@@ -829,8 +834,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int 
m,
   epoch_sec (neg_to_zero (get_stat_birthtime (statbuf;
   break;
 case 'W' + 256:
-  out_string (pformat, prefix_len,
-  epoch_ns (neg_to_zero (get_stat_birthtime (statbuf;
+  out_ns (pformat, prefix_len, neg_to_zero (get_stat_birthtime (statbuf)));
   break;
 case 'x':
   out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf)));
@@ -839,7 +843,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int 
m,
   out_string (pformat, prefix_len, epoch_sec (get_stat_atime (statbuf)));
   break;
 case 'X' + 256:
-  out_string (pformat, prefix_len, epoch_ns (get_stat_atime (statbuf)));
+  out_ns (pformat, prefix_len, get_stat_atime (statbuf));
   break;
 case 'y':
   out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf)));
@@ -848,7 +852,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int 
m,
   out_string (pformat, prefix_len, epoch_sec (get_stat_mtime (statbuf)));
   break;
 case 'Y' + 256:
-  out_string (pformat, prefix_len, epoch_ns (get_stat_mtime (statbuf)));
+  out_ns (pformat, prefix_len, get_stat_mtime (statbuf));
   break;
 case 'z':
   out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf)));
@@ -857,7 +861,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int 
m,
   out_string (pformat, prefix_len, epoch_sec (get_stat_ctime (statbuf)));
   break;
 case 'Z' + 256:
-  out_string (pformat, prefix_len, epoch_ns (get_stat_ctime (statbuf)));
+  out_ns (pformat, prefix_len, get_stat_ctime (statbuf));
   break;
 case 'C':
   fail |= out_file_context (pformat, prefix_len, filename);

diff --git a/doc/coreutils.

Re: [coreutils] stat: reverting recent %X %Y %Z change

2010-10-26 Thread Pádraig Brady
On 26/10/10 18:59, Jim Meyering wrote:
> Jim Meyering wrote:
>> Jim Meyering wrote:
>>
>>> Pádraig Brady wrote:
 On 22/10/10 18:43, Jim Meyering wrote:
> Part of reverting this change:
>
> stat now outputs the full sub-second resolution for the atime,
> mtime, and ctime values since the Epoch, when using the %X, %Y, and
> %Z directives of the --format option.  This matches the fact that
> %x, %y, and %z were already doing so for the human-readable variant.
>
> means considering whether to do the same sort of thing with the
> newly-added %W (birth time/crtime).  Note that %W currently expands to "-"
> on systems with no support (e.g., linux).
>
> I don't particularly like the idea of making stat do this:
>
> $ src/stat -c %W.%:W .
> -.-
>
> Rather, I have a slight preference to make it do this:
>
> $ src/stat -c %W.%:W .
> 0.0

 I prefer that as it would mean less special
 cases in code that uses the output.
>>>
>>> Exactly.
>>>
> In any case, I think %w should still expand to "-".
>
> The alternative is to leave %W separate, with no %:W variant.
> I.e., %W would continue to print floating point seconds.
> In that case, it would be inconsistent with %X, %Y and %Z.

 I don't like that.
>>>
>>> Thanks for the feedback!
>>
>> Here's a mostly-ready proposed change.
>>
>> I've just realized it doesn't mention the nanosecond field width issue:
>> the default is 9, and it's always zero-padded, but only to a width of 9,
>> which is surprising if you ever specify a larger field width:
>>
>> $ src/stat -c %12:W .
>>0
>>
>> I dislike such surprises...
> 
> I've adjusted things so that it's not so bad.
> 
> Setup:
> 
> $ touch -d '2010-10-21 18:43:33.00789' k
> 
> With the incremental patch below, you get "09" modifiers only
> when you specify no other modifier:
> 
> $ stat -c ns_%12:X_ k
> ns_ 789_
> $ stat -c ns_%:X_ k
> ns_00789_
> $ stat -c ns_%9:X_ k
> ns_  789_
> 
> diff --git a/src/stat.c b/src/stat.c
> index 9a6bb8f..9d3db1b 100644
> --- a/src/stat.c
> +++ b/src/stat.c
> @@ -471,14 +471,19 @@ epoch_sec (struct timespec t)
>return timetostr (t.tv_sec, str);
>  }
> 
> -/* Return a string representation (in static storage)
> -   of nanoseconds part of T.  */
> -static char * ATTRIBUTE_WARN_UNUSED_RESULT
> -epoch_ns (struct timespec t)
> +/* Output the number of nanoseconds, ARG.tv_nsec.  */
> +static void
> +out_ns (char *pformat, size_t prefix_len, struct timespec arg)
>  {
> -  static char str[10];
> -  sprintf (str, "%09ld", t.tv_nsec);
> -  return str;
> +  /* 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 off by a factor of 10 or more.  */
> +  strcpy (pformat + prefix_len, prefix_len == 1 ? "09ld" : "ld");
> +  printf (pformat, arg.tv_nsec);
>  }
> 
>  static void
> @@ -829,8 +834,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
> int m,
>epoch_sec (neg_to_zero (get_stat_birthtime (statbuf;
>break;
>  case 'W' + 256:
> -  out_string (pformat, prefix_len,
> -  epoch_ns (neg_to_zero (get_stat_birthtime (statbuf;
> +  out_ns (pformat, prefix_len, neg_to_zero (get_stat_birthtime 
> (statbuf)));
>break;
>  case 'x':
>out_string (pformat, prefix_len, human_time (get_stat_atime 
> (statbuf)));
> @@ -839,7 +843,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
> int m,
>out_string (pformat, prefix_len, epoch_sec (get_stat_atime (statbuf)));
>break;
>  case 'X' + 256:
> -  out_string (pformat, prefix_len, epoch_ns (get_stat_atime (statbuf)));
> +  out_ns (pformat, prefix_len, get_stat_atime (statbuf));
>break;
>  case 'y':
>out_string (pformat, prefix_len, human_time (get_stat_mtime 
> (statbuf)));
> @@ -848,7 +852,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
> int m,
>out_string (pformat, prefix_len, epoch_sec (get_stat_mtime (statbuf)));
>break;
>  case 'Y' + 256:
> -  out_string (pformat, prefix_len, epoch_ns (get_stat_mtime (statbuf)));
> +  out_ns (pformat, prefix_len, get_stat_mtime (statbuf));
>break;
>  case 'z':
>out_string (pformat, prefix_len, human_time (get_stat_ctime 
> (statbuf)));
> @@ -857,7 +861,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
> int m,
>out_string (pformat, prefix_len, epoch_sec (get_stat_ctime (statbuf)));
>break;
>  case 'Z'

Re: [coreutils] stat: reverting recent %X %Y %Z change

2010-10-27 Thread Jim Meyering
Pádraig Brady wrote:

> On 26/10/10 18:59, Jim Meyering wrote:
>> Jim Meyering wrote:
>>> Jim Meyering wrote:
>>>
 Pádraig Brady wrote:
> On 22/10/10 18:43, Jim Meyering wrote:
>> Part of reverting this change:
>>
>> stat now outputs the full sub-second resolution for the atime,
>> mtime, and ctime values since the Epoch, when using the %X, %Y, and
>> %Z directives of the --format option.  This matches the fact that
>> %x, %y, and %z were already doing so for the human-readable variant.
>>
>> means considering whether to do the same sort of thing with the
>> newly-added %W (birth time/crtime).  Note that %W currently expands to 
>> "-"
>> on systems with no support (e.g., linux).
>>
>> I don't particularly like the idea of making stat do this:
>>
>> $ src/stat -c %W.%:W .
>> -.-
>>
>> Rather, I have a slight preference to make it do this:
>>
>> $ src/stat -c %W.%:W .
>> 0.0
>
> I prefer that as it would mean less special
> cases in code that uses the output.

 Exactly.

>> In any case, I think %w should still expand to "-".
>>
>> The alternative is to leave %W separate, with no %:W variant.
>> I.e., %W would continue to print floating point seconds.
>> In that case, it would be inconsistent with %X, %Y and %Z.
>
> I don't like that.

 Thanks for the feedback!
>>>
>>> Here's a mostly-ready proposed change.
>>>
>>> I've just realized it doesn't mention the nanosecond field width issue:
>>> the default is 9, and it's always zero-padded, but only to a width of 9,
>>> which is surprising if you ever specify a larger field width:
>>>
>>> $ src/stat -c %12:W .
>>>0
>>>
>>> I dislike such surprises...
>>
>> I've adjusted things so that it's not so bad.
>>
>> Setup:
>>
>> $ touch -d '2010-10-21 18:43:33.00789' k
>>
>> With the incremental patch below, you get "09" modifiers only
>> when you specify no other modifier:
>>
>> $ stat -c ns_%12:X_ k
>> ns_ 789_
>> $ stat -c ns_%:X_ k
>> ns_00789_
>> $ stat -c ns_%9:X_ k
>> ns_  789_
>>
>> diff --git a/src/stat.c b/src/stat.c
>> index 9a6bb8f..9d3db1b 100644
>> --- a/src/stat.c
>> +++ b/src/stat.c
>> @@ -471,14 +471,19 @@ epoch_sec (struct timespec t)
>>return timetostr (t.tv_sec, str);
>>  }
>>
>> -/* Return a string representation (in static storage)
>> -   of nanoseconds part of T.  */
>> -static char * ATTRIBUTE_WARN_UNUSED_RESULT
>> -epoch_ns (struct timespec t)
>> +/* Output the number of nanoseconds, ARG.tv_nsec.  */
>> +static void
>> +out_ns (char *pformat, size_t prefix_len, struct timespec arg)
>>  {
>> -  static char str[10];
>> -  sprintf (str, "%09ld", t.tv_nsec);
>> -  return str;
>> +  /* 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 off by a factor of 10 or more.  */
>> +  strcpy (pformat + prefix_len, prefix_len == 1 ? "09ld" : "ld");
>> +  printf (pformat, arg.tv_nsec);
>>  }
>>
>>  static void
>> @@ -829,8 +834,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
>> int m,
>>epoch_sec (neg_to_zero (get_stat_birthtime (statbuf;
>>break;
>>  case 'W' + 256:
>> -  out_string (pformat, prefix_len,
>> -  epoch_ns (neg_to_zero (get_stat_birthtime (statbuf;
>> +  out_ns (pformat, prefix_len, neg_to_zero (get_stat_birthtime 
>> (statbuf)));
>>break;
>>  case 'x':
>>out_string (pformat, prefix_len, human_time (get_stat_atime 
>> (statbuf)));
>> @@ -839,7 +843,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
>> int m,
>>out_string (pformat, prefix_len, epoch_sec (get_stat_atime 
>> (statbuf)));
>>break;
>>  case 'X' + 256:
>> -  out_string (pformat, prefix_len, epoch_ns (get_stat_atime (statbuf)));
>> +  out_ns (pformat, prefix_len, get_stat_atime (statbuf));
>>break;
>>  case 'y':
>>out_string (pformat, prefix_len, human_time (get_stat_mtime 
>> (statbuf)));
>> @@ -848,7 +852,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned 
>> int m,
>>out_string (pformat, prefix_len, epoch_sec (get_stat_mtime 
>> (statbuf)));
>>break;
>>  case 'Y' + 256:
>> -  out_string (pformat, prefix_len, epoch_ns (get_stat_mtime (statbuf)));
>> +  out_ns (pformat, prefix_len, get_stat_mtime (statbuf));
>>break;
>>  case 'z':
>>out_string (pformat, prefix_len, human_time (get_stat_ctime 
>> (statbuf)));
>> @@ -857,7 +861,7 @@ print_stat

Re: [coreutils] stat: reverting recent %X %Y %Z change

2010-10-28 Thread Jim Meyering
Jim Meyering wrote:
...
> I think I have fixed things, finally.
> Here's how my latest works:
>
>   $ touch -d '2010-10-21 18:43:33.012345678' k
>   $ src/stat -c %3:X k
>   12345678
>   $ src/stat -c %3.3:X k
>12
>   $ src/stat -c %03.3:X k
>   012
>   $ src/stat -c %:X k
>   012345678
>   $ src/stat -c %03.3:X k
>   012
>   $ src/stat -c %010.3:X k
>   12
>   $ src/stat -c %-3.3:X k
>   12
>
> I'll post code when I have tests.

Here's an incremental change (only for reference) that adds support
for the above as well as tests.  The complete change (including
this incremental one) is below.  No rush on the review.
I'm unlikely to do anything more with this until Tuesday.

>From 1fa5ce9909bdb56665bd149fe598db740358ed16 Mon Sep 17 00:00:00 2001
From: Jim Meyering 
Date: Wed, 27 Oct 2010 12:04:31 +0200
Subject: [PATCH] honor precision, add tests

---
 src/stat.c  |   57 ---
 tests/Makefile.am   |1 +
 tests/misc/stat-nanoseconds |   35 ++
 3 files changed, 89 insertions(+), 4 deletions(-)
 create mode 100755 tests/misc/stat-nanoseconds

diff --git a/src/stat.c b/src/stat.c
index 9d3db1b..a132b5f 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -70,6 +70,7 @@
 #include "stat-time.h"
 #include "strftime.h"
 #include "find-mount-point.h"
+#include "xstrtol.h"
 #include "xvasprintf.h"

 #if USE_STATVFS
@@ -471,7 +472,36 @@ epoch_sec (struct timespec t)
   return timetostr (t.tv_sec, str);
 }

-/* Output the number of nanoseconds, ARG.tv_nsec.  */
+/* Return 10^N, for N in 0..9.  Otherwise, return 0.  */
+static unsigned int
+e10 (unsigned int n)
+{
+  static unsigned int pow10[] =
+{ 1, 10, 100, 1000, 1, 10, 100, 1000, 1, 
10 };
+  return n < ARRAY_CARDINALITY (pow10) ? pow10[n] : 0;
+}
+
+/* Given the modifiers, FMT, of a format string, return
+   the precision, if specified, else 0.  */
+static unsigned int
+format_precision (char *fmt, size_t n_bytes)
+{
+  char const *decimal = memchr (fmt, '.', n_bytes);
+  if (decimal == NULL)
+return 0;
+  char const *prec = decimal + 1;
+  unsigned long tmp;
+  fmt[n_bytes] = '\0';
+  if (xstrtoul (prec, NULL, 10, &tmp, NULL) != LONGINT_OK
+  || UINT_MAX < tmp)
+return 0;
+
+  return tmp;
+}
+
+/* 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)
 {
@@ -481,9 +511,28 @@ out_ns (char *pformat, size_t prefix_len, struct timespec 
arg)
  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 off by a factor of 10 or more.  */
-  strcpy (pformat + prefix_len, prefix_len == 1 ? "09ld" : "ld");
-  printf (pformat, arg.tv_nsec);
+ fraction would be off by a factor of 10 or more.  */
+  unsigned long int ns = arg.tv_nsec;
+  unsigned int prec;
+  char const *fmt;
+
+  if (prefix_len == 1)
+fmt = "09lu";
+  else
+{
+  fmt = "lu";
+  if ((prec = format_precision (pformat + 1, prefix_len - 1)) < 9
+  && prec != 0)
+{
+  /* Honor precision, and then shorten prefix_len so that
+ we elide the ".PREC" suffix from the format string.  */
+  ns /= e10 (9 - prec);
+  prefix_len = strchr (pformat, '.') - pformat;
+}
+}
+
+  strcpy (pformat + prefix_len, fmt);
+  printf (pformat, ns);
 }

 static void
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 84db367..dd1c509 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -244,6 +244,7 @@ TESTS = \
   misc/stat-fmt\
   misc/stat-hyphen \
   misc/stat-mount  \
+  misc/stat-nanoseconds\
   misc/stat-printf \
   misc/stat-slash  \
   misc/stdbuf  \
diff --git a/tests/misc/stat-nanoseconds b/tests/misc/stat-nanoseconds
new file mode 100755
index 000..b7a5daf
--- /dev/null
+++ b/tests/misc/stat-nanoseconds
@@ -0,0 +1,35 @@
+#!/bin/sh
+# Exercise format strings involving %:X, %:Y, etc.
+
+# 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

Re: [coreutils] stat: reverting recent %X %Y %Z change

2010-10-29 Thread Pádraig Brady
On 28/10/10 12:03, Jim Meyering wrote:

>>From 4ee918f1ca742c9b02d00e703625b388b309bcc1 Mon Sep 17 00:00:00 2001
> From: Jim Meyering 
> Date: Thu, 21 Oct 2010 18:41:24 +0200
> Subject: [PATCH] stat: revert %X-%Y-%Z change; use e.g., %:X to print 
> fractional seconds
> 
> This reverts part of the recent commit 9069af45,
> "stat: print timestamps to full resolution", which made %X, %Y, %Z
> print floating point numbers.  We prefer to retain portability of
> %X, %Y and %Z uses, while still providing access to full-resolution
> time stamps via modified format strings.  Also make the new
> %W consistent.
> * src/stat.c: Include "xstrtol.h".
> (print_it): Accept a new %...:[XYZ] format directive,
> e.g., %:X, to print the nanoseconds portion of the corresponding time.
> For example, %3.3:Y prints the zero-padded, truncated, milliseconds
> part of the time of last modification.

The above needs to be updated I think
as the current code needs a 0 specified.

$ src/stat -c [%3.3:Y] /usr
[ 31]

$ src/stat -c [%03.3:Y] /usr
[031]

I notice that this does not truncate as I would expect.
$ src/stat -c [%.3:Y] /usr
[31]

Should we perhaps treat the bit before the '.' as
the width for %ld (defaulting to 09), and the bit
after the '.' as the width for %s?

I've not thought much about that really.

have to run,
Pádraig.