Subject: bug#7325: new test failure due to non-portability of printf formats like %05.3s

From: Jim Meyering <[email-masked]>
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 <[email-masked]>
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 <[email-masked]>
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 <[email-masked]>
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