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.000000000
>>>>>
>>>>> 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 .
>>>        000000000
>>>
>>> I dislike such surprises...
>>
>> I've adjusted things so that it's not so bad.
>>
>> Setup:
>>
>>     $ touch -d '2010-10-21 18:43:33.000000789' 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_000000789_
>>     $ 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.texi b/doc/coreutils.texi
>> index 94e8ebf..58a700b 100644
>> --- a/doc/coreutils.texi
>> +++ b/doc/coreutils.texi
>> @@ -10699,18 +10699,23 @@ stat invocation
>>  @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: 0-padded nanoseconds remainder, 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: 0-padded nanoseconds remainder
>> +...@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: 0-padded nanoseconds remainder
>> +...@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: 0-padded nanoseconds remainder
>> +...@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}.
>> +
>>  The mount point printed by @samp{%m} is similar to that output
>>  by @command{df}, except that:
>>  @itemize @bullet
>>
>> Here's the combined patch:
>>
>>>From eba6292f45c9b46fb8a64f8a017bf2e9437cc60e Mon Sep 17 00:00:00 2001
>> From: Jim Meyering <meyer...@redhat.com>
>> 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 (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.
>
> That is no longer the case since you're using %ld rather than %s
> $ ./src/stat -c [%12.10:Y] /
> [  0521544487]
> $ ./src/stat -c [%3.3:Y] /
> [521544487]
>
> Do we still want to support truncation?
> It seems useful. date supports it but unconventionally
>
> $ src/date '+[%N]' --ref=/usr
> [031367045]
> $ src/date '+[%-N]' --ref=/usr
> [31367045]
> $ src/date '+[%12N]' --ref=/usr
> [000031367045]
> $ src/date '+[%12.3N]' --ref=/usr
> [        %12.3N]
> $ src/date '+[%3N]' --ref=/usr
> [031]

Thanks for another good catch.

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
  0000000012
  $ src/stat -c %-3.3:X k
  12

I'll post code when I have tests.

Reply via email to