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])) {