bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

imported sub-second file time stamp improvements from tar via gnulib


From: Paul Eggert
Subject: imported sub-second file time stamp improvements from tar via gnulib
Date: Fri, 16 Sep 2005 01:02:06 -0700
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

I installed this into coreutils, to get some improved support for
sub-second file time stamps on platforms like OpenBSD.

2005-09-16  Paul Eggert  <address@hidden>

        * src/copy.c: Include stat-time.h.
        (copy_internal): Use its functions instead of the obsolete
        TIMESPEC_NS macro.
        * src/cp.c (re_protect): Likewise.
        * src/date.c (main): Likewise.
        * src/du.c (struct duinfo, duinfo_init, duinfo_set, duinfo_add):
        (show_date, print_size, process_file): Likewise.
        * src/install.c (change_timestamps): Likewise.
        * src/ls.c (cmp_ctime, cmp_mtime, cmp_atime, print_long_format):
        Likewise.
        * src/pr.c (init_header): Likewise.
        * src/stat.c (human_time, print_stat): Likewise.
        * src/tail.c (record_open_fd, tail_forever): Likewise.
        * src/test.c (get_mtime, binary_operator): Likewise.
        * src/touch.c (touch, main): Likewise.
        * src/test.c (get_mtime): Renamed from age_of.  All uses changed.
        * m4/jm-macros.m4 (gl_CHECK_ALL_TYPES): Do not require
        AC_STRUCT_ST_MTIM_NSEC; it's obsolete.
        * m4/prereq.m4 (gl_PREREQ): Require gl_STAT_TIME.
        * lib/.cppi-disable: Add stat-time.h.

        Import from gnulib.

        Import from gnulib.
        * lib/stat-time.h: New file.
        * lib/timespec.h (ST_TIME_CMP_NS, ST_TIME_CMP, ATIME_CMP, CTIME_CMP):
        (MTIME_CMP, TIMESPEC_NS): Remove.  Now done by stat-time.h,
        in a different way.
        (timespec_cmp): New function.
        * lib/utimecmp.c: Include stat-time.h.
        (SYSCALL_RESOLUTION): Depend on whether various struct stat
        members exist, not on the obsolescent ST_MTIM_NSEC.
        (utimecmp): Use the new stat-time functions rater than TIMESPEC_NS.
        * m4/st_mtim.m4: Remove.  Superseded by...
        * m4/stat-time.m4: New file.
        * m4/timespec.m4 (gl_TIMESPEC): Require AC_C_INLINE.
        Do not invoke AC_STRUCT_ST_MTIM_NSEC; no longer needed.

Index: lib/timespec.h
===================================================================
RCS file: /fetish/cu/lib/timespec.h,v
retrieving revision 1.5
diff -p -u -r1.5 timespec.h
--- lib/timespec.h      14 May 2005 07:58:07 -0000      1.5
+++ lib/timespec.h      16 Sep 2005 07:20:30 -0000
@@ -42,22 +42,15 @@ struct timespec
 };
 # endif
 
-# ifdef ST_MTIM_NSEC
-#  define ST_TIME_CMP_NS(a, b, ns) ((a).ns < (b).ns ? -1 : (a).ns > (b).ns)
-# else
-#  define ST_TIME_CMP_NS(a, b, ns) 0
-# endif
-# define ST_TIME_CMP(a, b, s, ns) \
-   ((a).s < (b).s ? -1 : (a).s > (b).s ? 1 : ST_TIME_CMP_NS(a, b, ns))
-# define ATIME_CMP(a, b) ST_TIME_CMP (a, b, st_atime, st_atim.ST_MTIM_NSEC)
-# define CTIME_CMP(a, b) ST_TIME_CMP (a, b, st_ctime, st_ctim.ST_MTIM_NSEC)
-# define MTIME_CMP(a, b) ST_TIME_CMP (a, b, st_mtime, st_mtim.ST_MTIM_NSEC)
-
-# ifdef ST_MTIM_NSEC
-#  define TIMESPEC_NS(timespec) ((timespec).ST_MTIM_NSEC)
-# else
-#  define TIMESPEC_NS(timespec) 0
-# endif
+/* Return negative, zero, positive if A < B, A == B, A > B, respectively.
+   Assume the nanosecond components are in range, or close to it.  */
+static inline int
+timespec_cmp (struct timespec a, struct timespec b)
+{
+  return (a.tv_sec < b.tv_sec ? -1
+         : a.tv_sec > b.tv_sec ? 1
+         : a.tv_nsec - b.tv_nsec);
+}
 
 # if ! HAVE_DECL_NANOSLEEP
 /* Don't specify a prototype here.  Some systems (e.g., OSF) declare
Index: lib/utimecmp.c
===================================================================
RCS file: /fetish/cu/lib/utimecmp.c,v
retrieving revision 1.3
diff -p -u -r1.3 utimecmp.c
--- lib/utimecmp.c      14 May 2005 07:58:07 -0000      1.3
+++ lib/utimecmp.c      16 Sep 2005 07:20:30 -0000
@@ -36,6 +36,7 @@
 #include <stdlib.h>
 #include "hash.h"
 #include "intprops.h"
+#include "stat-time.h"
 #include "timespec.h"
 #include "utimens.h"
 #include "xalloc.h"
@@ -56,7 +57,12 @@ enum { BILLION = 1000 * 1000 * 1000 };
 /* Best possible resolution that utimens can set and stat can return,
    due to system-call limitations.  It must be a power of 10 that is
    no greater than 1 billion.  */
-#if HAVE_WORKING_UTIMES && defined ST_MTIM_NSEC
+#if (HAVE_WORKING_UTIMES                                       \
+     && (defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC              \
+        || defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC       \
+        || defined HAVE_STRUCT_STAT_ST_ATIMENSEC               \
+        || defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC    \
+        || defined HAVE_STRUCT_STAT_ST_SPARE1))
 enum { SYSCALL_RESOLUTION = 1000 };
 #else
 enum { SYSCALL_RESOLUTION = BILLION };
@@ -139,8 +145,8 @@ utimecmp (char const *dst_name,
   /* Destination and source time stamps.  */
   time_t dst_s = dst_stat->st_mtime;
   time_t src_s = src_stat->st_mtime;
-  int dst_ns = TIMESPEC_NS (dst_stat->st_mtim);
-  int src_ns = TIMESPEC_NS (src_stat->st_mtim);
+  int dst_ns = get_stat_mtime_ns (dst_stat);
+  int src_ns = get_stat_mtime_ns (src_stat);
 
   if (options & UTIMECMP_TRUNCATE_SOURCE)
     {
@@ -186,8 +192,8 @@ utimecmp (char const *dst_name,
          time_t dst_a_s = dst_stat->st_atime;
          time_t dst_c_s = dst_stat->st_ctime;
          time_t dst_m_s = dst_s;
-         int dst_a_ns = TIMESPEC_NS (dst_stat->st_atim);
-         int dst_c_ns = TIMESPEC_NS (dst_stat->st_ctim);
+         int dst_a_ns = get_stat_atime_ns (dst_stat);
+         int dst_c_ns = get_stat_ctime_ns (dst_stat);
          int dst_m_ns = dst_ns;
 
          /* Set RES to an upper bound on the file system resolution
@@ -280,7 +286,7 @@ utimecmp (char const *dst_name,
 
                if (stat_result
                    | (dst_status.st_mtime ^ dst_m_s)
-                   | (TIMESPEC_NS (dst_status.st_mtim) ^ dst_m_ns))
+                   | (get_stat_mtime_ns (&dst_status) ^ dst_m_ns))
                  {
                    /* The modification time changed, or we can't tell whether
                       it changed.  Change it back as best we can.  */
@@ -298,7 +304,7 @@ utimecmp (char const *dst_name,
              {
                int old_res = res;
                int a = (BILLION * (dst_status.st_mtime & 1)
-                        + TIMESPEC_NS (dst_status.st_mtim));
+                        + get_stat_mtime_ns (&dst_status));
 
                res = SYSCALL_RESOLUTION;
 
Index: m4/jm-macros.m4
===================================================================
RCS file: /fetish/cu/m4/jm-macros.m4,v
retrieving revision 1.227
diff -p -u -r1.227 jm-macros.m4
--- m4/jm-macros.m4     2 Aug 2005 20:48:58 -0000       1.227
+++ m4/jm-macros.m4     16 Sep 2005 07:20:30 -0000
@@ -256,7 +256,6 @@ AC_DEFUN([gl_CHECK_ALL_TYPES],
   ])
   AC_REQUIRE([AC_STRUCT_ST_BLOCKS])
 
-  AC_REQUIRE([AC_STRUCT_ST_MTIM_NSEC])
   AC_REQUIRE([AC_STRUCT_ST_DM_MODE])
 
   AC_REQUIRE([AC_TYPE_GETGROUPS])
Index: m4/prereq.m4
===================================================================
RCS file: /fetish/cu/m4/prereq.m4,v
retrieving revision 1.118
diff -p -u -r1.118 prereq.m4
--- m4/prereq.m4        5 Jul 2005 06:30:27 -0000       1.118
+++ m4/prereq.m4        16 Sep 2005 07:20:30 -0000
@@ -133,6 +133,7 @@ AC_DEFUN([gl_PREREQ],
   AC_REQUIRE([gl_SETTIME])
   AC_REQUIRE([gl_SHA1])
   AC_REQUIRE([gl_STAT_MACROS])
+  AC_REQUIRE([gl_STAT_TIME])
   AC_REQUIRE([gl_STDIO_SAFER])
   AC_REQUIRE([gl_STDLIB_SAFER])
   AC_REQUIRE([gl_STRCASE])
Index: m4/timespec.m4
===================================================================
RCS file: /fetish/cu/m4/timespec.m4,v
retrieving revision 1.10
diff -p -u -r1.10 timespec.m4
--- m4/timespec.m4      29 Jan 2005 00:16:39 -0000      1.10
+++ m4/timespec.m4      16 Sep 2005 07:20:30 -0000
@@ -1,4 +1,4 @@
-#serial 10
+#serial 11
 
 # Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -12,10 +12,10 @@ AC_DEFUN([gl_TIMESPEC],
   AC_LIBSOURCES([timespec.h])
 
   dnl Prerequisites of lib/timespec.h.
+  AC_REQUIRE([AC_C_INLINE])
   AC_REQUIRE([AC_HEADER_TIME])
   AC_CHECK_HEADERS_ONCE(sys/time.h)
   gl_CHECK_TYPE_STRUCT_TIMESPEC
-  AC_STRUCT_ST_MTIM_NSEC
 
   dnl Persuade glibc <time.h> to declare nanosleep().
   AC_REQUIRE([AC_GNU_SOURCE])
Index: src/copy.c
===================================================================
RCS file: /fetish/cu/src/copy.c,v
retrieving revision 1.187
diff -p -u -r1.187 copy.c
--- src/copy.c  11 Jul 2005 18:28:19 -0000      1.187
+++ src/copy.c  16 Sep 2005 07:21:11 -0000
@@ -45,6 +45,7 @@
 #include "quote.h"
 #include "same.h"
 #include "savedir.h"
+#include "stat-time.h"
 #include "utimecmp.h"
 #include "utimens.h"
 #include "xreadlink.h"
@@ -1567,10 +1568,8 @@ copy_internal (char const *src_name, cha
     {
       struct timespec timespec[2];
 
-      timespec[0].tv_sec = src_sb.st_atime;
-      timespec[0].tv_nsec = TIMESPEC_NS (src_sb.st_atim);
-      timespec[1].tv_sec = src_sb.st_mtime;
-      timespec[1].tv_nsec = TIMESPEC_NS (src_sb.st_mtim);
+      timespec[0] = get_stat_atime (&src_sb);
+      timespec[1] = get_stat_mtime (&src_sb);
 
       if (utimens (dst_name, timespec) != 0)
        {
Index: src/cp.c
===================================================================
RCS file: /fetish/cu/src/cp.c,v
retrieving revision 1.214
diff -p -u -r1.214 cp.c
--- src/cp.c    3 Jul 2005 16:49:23 -0000       1.214
+++ src/cp.c    16 Sep 2005 07:21:11 -0000
@@ -33,6 +33,7 @@
 #include "filenamecat.h"
 #include "quote.h"
 #include "quotearg.h"
+#include "stat-time.h"
 #include "utimens.h"
 
 #define ASSIGN_BASENAME_STRDUPA(Dest, File_name)       \
@@ -304,10 +305,8 @@ re_protect (char const *const_dst_name, 
        {
          struct timespec timespec[2];
 
-         timespec[0].tv_sec = src_sb.st_atime;
-         timespec[0].tv_nsec = TIMESPEC_NS (src_sb.st_atim);
-         timespec[1].tv_sec = src_sb.st_mtime;
-         timespec[1].tv_nsec = TIMESPEC_NS (src_sb.st_mtim);
+         timespec[0] = get_stat_atime (&src_sb);
+         timespec[1] = get_stat_mtime (&src_sb);
 
          if (utimens (dst_name, timespec))
            {
Index: src/date.c
===================================================================
RCS file: /fetish/cu/src/date.c,v
retrieving revision 1.156
diff -p -u -r1.156 date.c
--- src/date.c  13 Sep 2005 22:08:41 -0000      1.156
+++ src/date.c  16 Sep 2005 07:21:11 -0000
@@ -33,6 +33,7 @@
 #include "inttostr.h"
 #include "posixtm.h"
 #include "quote.h"
+#include "stat-time.h"
 #include "strftime.h"
 #include "xanstrftime.h"
 
@@ -494,10 +495,9 @@ main (int argc, char **argv)
          /* (option_specified_date || set_date) */
          if (reference != NULL)
            {
-             if (stat (reference, &refstats))
+             if (stat (reference, &refstats) != 0)
                error (EXIT_FAILURE, errno, "%s", reference);
-             when.tv_sec = refstats.st_mtime;
-             when.tv_nsec = TIMESPEC_NS (refstats.st_mtim);
+             when = get_stat_mtime (&refstats);
            }
          else
            {
Index: src/du.c
===================================================================
RCS file: /fetish/cu/src/du.c,v
retrieving revision 1.220
diff -p -u -r1.220 du.c
--- src/du.c    7 Sep 2005 06:08:01 -0000       1.220
+++ src/du.c    16 Sep 2005 07:21:12 -0000
@@ -41,6 +41,7 @@
 #include "quotearg.h"
 #include "readtokens0.h"
 #include "same.h"
+#include "stat-time.h"
 #include "strftime.h"
 #include "xanstrftime.h"
 #include "xfts.h"
@@ -84,10 +85,9 @@ struct duinfo
   /* Size of files in directory.  */
   uintmax_t size;
 
-  /* Latest time stamp found.  If dmax == TYPE_MINIMUM (time_t) && nsec < 0,
-     no time stamp has been found.  */
-  time_t dmax;
-  int nsec;
+  /* Latest time stamp found.  If tmax.tv_sec == TYPE_MINIMUM (time_t)
+     && tmax.tv_nsec < 0, no time stamp has been found.  */
+  struct timespec tmax;
 };
 
 /* Initialize directory data.  */
@@ -95,17 +95,16 @@ static inline void
 duinfo_init (struct duinfo *a)
 {
   a->size = 0;
-  a->dmax = TYPE_MINIMUM (time_t);
-  a->nsec = -1;
+  a->tmax.tv_sec = TYPE_MINIMUM (time_t);
+  a->tmax.tv_nsec = -1;
 }
 
 /* Set directory data.  */
 static inline void
-duinfo_set (struct duinfo *a, uintmax_t size, time_t dmax, int nsec)
+duinfo_set (struct duinfo *a, uintmax_t size, struct timespec tmax)
 {
   a->size = size;
-  a->dmax = dmax;
-  a->nsec = nsec;
+  a->tmax = tmax;
 }
 
 /* Accumulate directory data.  */
@@ -113,12 +112,8 @@ static inline void
 duinfo_add (struct duinfo *a, struct duinfo const *b)
 {
   a->size += b->size;
-  if (a->dmax < b->dmax
-      || (a->dmax == b->dmax && a->nsec < b->nsec))
-    {
-      a->dmax = b->dmax;
-      a->nsec = b->nsec;
-    }
+  if (timespec_cmp (a->tmax, b->tmax) < 0)
+    a->tmax = b->tmax;
 }
 
 /* A structure for per-directory level information.  */
@@ -406,27 +401,27 @@ hash_init (void)
 }
 
 /* FIXME: this code is nearly identical to code in date.c  */
-/* Display the date and time in WHEN/NSEC according to the format specified
+/* Display the date and time in WHEN according to the format specified
    in TIME_FORMAT.  If TIME_FORMAT is NULL, use the standard output format.
    Return zero if successful.  */
 
 static void
-show_date (const char *format, time_t when, int nsec)
+show_date (const char *format, struct timespec when)
 {
   char *out;
-  struct tm *tm = localtime (&when);
+  struct tm *tm = localtime (&when.tv_sec);
   if (! tm)
     {
       char buf[INT_BUFSIZE_BOUND (intmax_t)];
       error (0, 0, _("time %s is out of range"),
             (TYPE_SIGNED (time_t)
-             ? imaxtostr (when, buf)
-             : umaxtostr (when, buf)));
+             ? imaxtostr (when.tv_sec, buf)
+             : umaxtostr (when.tv_sec, buf)));
       fputs (buf, stdout);
       return;
     }
 
-  out = xanstrftime (format, tm, 0, nsec);
+  out = xanstrftime (format, tm, 0, when.tv_nsec);
   fputs (out, stdout);
   free (out);
 }
@@ -450,7 +445,7 @@ print_size (const struct duinfo *pdui, c
   if (opt_time)
     {
       putchar ('\t');
-      show_date (time_format, pdui->dmax, pdui->nsec);
+      show_date (time_format, pdui->tmax);
     }
   printf ("\t%s%c", string, opt_nul_terminate_output ? '\0' : '\n');
   fflush (stdout);
@@ -539,12 +534,9 @@ process_file (FTS *fts, FTSENT *ent)
                  (apparent_size
                   ? sb->st_size
                   : ST_NBLOCKS (*sb) * ST_NBLOCKSIZE),
-                 (time_type == time_ctime ? sb->st_ctime
-                  : time_type == time_atime ? sb->st_atime
-                  : sb->st_mtime),
-                 (time_type == time_ctime ? TIMESPEC_NS (sb->st_ctim)
-                  : time_type == time_atime ? TIMESPEC_NS (sb->st_atim)
-                  : TIMESPEC_NS (sb->st_mtim)));
+                 (time_type == time_mtime ? get_stat_mtime (sb)
+                  : time_type == time_atime ? get_stat_atime (sb)
+                  : get_stat_ctime (sb)));
     }
 
   level = ent->fts_level;
Index: src/install.c
===================================================================
RCS file: /fetish/cu/src/install.c,v
retrieving revision 1.186
diff -p -u -r1.186 install.c
--- src/install.c       16 Jun 2005 09:15:23 -0000      1.186
+++ src/install.c       16 Sep 2005 07:21:12 -0000
@@ -35,6 +35,7 @@
 #include "mkdir-p.h"
 #include "modechange.h"
 #include "quote.h"
+#include "stat-time.h"
 #include "utimens.h"
 #include "xstrtol.h"
 
@@ -536,10 +537,8 @@ change_timestamps (const char *from, con
       return false;
     }
 
-  timespec[0].tv_sec = stb.st_atime;
-  timespec[0].tv_nsec = TIMESPEC_NS (stb.st_atim);
-  timespec[1].tv_sec = stb.st_mtime;
-  timespec[1].tv_nsec = TIMESPEC_NS (stb.st_mtim);
+  timespec[0] = get_stat_atime (&stb);
+  timespec[1] = get_stat_mtime (&stb);
   if (utimens (to, timespec))
     {
       error (0, errno, _("cannot set time stamps for %s"), quote (to));
Index: src/ls.c
===================================================================
RCS file: /fetish/cu/src/ls.c,v
retrieving revision 1.398
diff -p -u -r1.398 ls.c
--- src/ls.c    5 Sep 2005 17:12:07 -0000       1.398
+++ src/ls.c    16 Sep 2005 07:21:12 -0000
@@ -123,6 +123,7 @@ int wcwidth ();
 #include "quote.h"
 #include "quotearg.h"
 #include "same.h"
+#include "stat-time.h"
 #include "strftime.h"
 #include "strverscmp.h"
 #include "xstrtol.h"
@@ -2855,7 +2856,8 @@ static inline int
 cmp_ctime (struct fileinfo const *a, struct fileinfo const *b,
           int (*cmp) (char const *, char const *))
 {
-  int diff = CTIME_CMP (b->stat, a->stat);
+  int diff = timespec_cmp (get_stat_ctime (&b->stat),
+                          get_stat_ctime (&a->stat));
   return diff ? diff : cmp (a->name, b->name);
 }
 static int compare_ctime (V a, V b) { return cmp_ctime (a, b, xstrcoll); }
@@ -2867,7 +2869,8 @@ static inline int
 cmp_mtime (struct fileinfo const *a, struct fileinfo const *b,
           int (*cmp) (char const *, char const *))
 {
-  int diff = MTIME_CMP (b->stat, a->stat);
+  int diff = timespec_cmp (get_stat_mtime (&b->stat),
+                          get_stat_mtime (&a->stat));
   return diff ? diff : cmp (a->name, b->name);
 }
 static int compare_mtime (V a, V b) { return cmp_mtime (a, b, xstrcoll); }
@@ -2879,7 +2882,8 @@ static inline int
 cmp_atime (struct fileinfo const *a, struct fileinfo const *b,
           int (*cmp) (char const *, char const *))
 {
-  int diff = ATIME_CMP (b->stat, a->stat);
+  int diff = timespec_cmp (get_stat_atime (&b->stat),
+                          get_stat_atime (&a->stat));
   return diff ? diff : cmp (a->name, b->name);
 }
 static int compare_atime (V a, V b) { return cmp_atime (a, b, xstrcoll); }
@@ -3231,7 +3235,8 @@ print_long_format (const struct fileinfo
   size_t s;
   char *p;
   time_t when;
-  int when_ns IF_LINT (= 0);
+  int when_ns;
+  struct timespec when_timespec;
   struct tm *when_local;
 
   /* Compute mode string.  On most systems, it's based on st_mode.
@@ -3245,19 +3250,19 @@ print_long_format (const struct fileinfo
   switch (time_type)
     {
     case time_ctime:
-      when = f->stat.st_ctime;
-      when_ns = TIMESPEC_NS (f->stat.st_ctim);
+      when_timespec = get_stat_ctime (&f->stat);
       break;
     case time_mtime:
-      when = f->stat.st_mtime;
-      when_ns = TIMESPEC_NS (f->stat.st_mtim);
+      when_timespec = get_stat_mtime (&f->stat);
       break;
     case time_atime:
-      when = f->stat.st_atime;
-      when_ns = TIMESPEC_NS (f->stat.st_atim);
+      when_timespec = get_stat_atime (&f->stat);
       break;
     }
 
+  when = when_timespec.tv_sec;
+  when_ns = when_timespec.tv_nsec;
+
   p = buf;
 
   if (print_inode)
@@ -3337,7 +3342,7 @@ print_long_format (const struct fileinfo
       p[-1] = ' ';
     }
 
-  when_local = localtime (&when);
+  when_local = localtime (&when_timespec.tv_sec);
   s = 0;
   *p = '\1';
 
Index: src/pr.c
===================================================================
RCS file: /fetish/cu/src/pr.c,v
retrieving revision 1.156
diff -p -u -r1.156 pr.c
--- src/pr.c    12 Aug 2005 07:29:51 -0000      1.156
+++ src/pr.c    16 Sep 2005 07:21:12 -0000
@@ -319,6 +319,7 @@
 #include "inttostr.h"
 #include "mbswidth.h"
 #include "quote.h"
+#include "stat-time.h"
 #include "stdio--.h"
 #include "strftime.h"
 #include "xstrtol.h"
@@ -1656,7 +1657,7 @@ init_header (char *filename, int desc)
 {
   char *buf = NULL;
   struct stat st;
-  time_t s;
+  struct timespec t;
   int ns;
   struct tm *tm;
 
@@ -1664,25 +1665,22 @@ init_header (char *filename, int desc)
   if (STREQ (filename, "-"))
     desc = -1;
   if (0 <= desc && fstat (desc, &st) == 0)
-    {
-      s = st.st_mtime;
-      ns = TIMESPEC_NS (st.st_mtim);
-    }
+    t = get_stat_mtime (&st);
   else
     {
       static struct timespec timespec;
       if (! timespec.tv_sec)
        gettime (&timespec);
-      s = timespec.tv_sec;
-      ns = timespec.tv_nsec;
+      t = timespec;
     }
 
-  tm = localtime (&s);
+  ns = t.tv_nsec;
+  tm = localtime (&t.tv_sec);
   if (tm == NULL)
     {
       buf = xmalloc (INT_BUFSIZE_BOUND (long int)
                     + MAX (10, INT_BUFSIZE_BOUND (int)));
-      sprintf (buf, "%ld.%09d", (long int) s, ns);
+      sprintf (buf, "%ld.%09d", (long int) t.tv_sec, ns);
     }
   else
     {
Index: src/stat.c
===================================================================
RCS file: /fetish/cu/src/stat.c,v
retrieving revision 1.87
diff -p -u -r1.87 stat.c
--- src/stat.c  14 May 2005 07:58:37 -0000      1.87
+++ src/stat.c  16 Sep 2005 07:21:12 -0000
@@ -52,6 +52,7 @@
 #include "inttostr.h"
 #include "quote.h"
 #include "quotearg.h"
+#include "stat-time.h"
 #include "strftime.h"
 #include "xreadlink.h"
 
@@ -280,18 +281,18 @@ human_access (struct stat const *statbuf
 }
 
 static char *
-human_time (time_t t, int t_ns)
+human_time (struct timespec t)
 {
   static char str[MAX (INT_BUFSIZE_BOUND (intmax_t),
                       (INT_STRLEN_BOUND (int) /* YYYY */
                        + 1 /* because YYYY might equal INT_MAX + 1900 */
                        + sizeof "-MM-DD HH:MM:SS.NNNNNNNNN +ZZZZ"))];
-  struct tm const *tm = localtime (&t);
+  struct tm const *tm = localtime (&t.tv_sec);
   if (tm == NULL)
     return (TYPE_SIGNED (time_t)
-           ? imaxtostr (t, str)
-           : umaxtostr (t, str));
-  nstrftime (str, sizeof str, "%Y-%m-%d %H:%M:%S.%N %z", tm, 0, t_ns);
+           ? imaxtostr (t.tv_sec, str)
+           : umaxtostr (t.tv_sec, str));
+  nstrftime (str, sizeof str, "%Y-%m-%d %H:%M:%S.%N %z", tm, 0, t.tv_nsec);
   return str;
 }
 
@@ -506,8 +507,7 @@ print_stat (char *pformat, size_t buf_le
       break;
     case 'x':
       xstrcat (pformat, buf_len, "s");
-      printf (pformat, human_time (statbuf->st_atime,
-                                  TIMESPEC_NS (statbuf->st_atim)));
+      printf (pformat, human_time (get_stat_atime (statbuf)));
       break;
     case 'X':
       xstrcat (pformat, buf_len, TYPE_SIGNED (time_t) ? "ld" : "lu");
@@ -515,8 +515,7 @@ print_stat (char *pformat, size_t buf_le
       break;
     case 'y':
       xstrcat (pformat, buf_len, "s");
-      printf (pformat, human_time (statbuf->st_mtime,
-                                  TIMESPEC_NS (statbuf->st_mtim)));
+      printf (pformat, human_time (get_stat_mtime (statbuf)));
       break;
     case 'Y':
       xstrcat (pformat, buf_len, TYPE_SIGNED (time_t) ? "ld" : "lu");
@@ -524,8 +523,7 @@ print_stat (char *pformat, size_t buf_le
       break;
     case 'z':
       xstrcat (pformat, buf_len, "s");
-      printf (pformat, human_time (statbuf->st_ctime,
-                                  TIMESPEC_NS (statbuf->st_ctim)));
+      printf (pformat, human_time (get_stat_ctime (statbuf)));
       break;
     case 'Z':
       xstrcat (pformat, buf_len, TYPE_SIGNED (time_t) ? "ld" : "lu");
Index: src/tail.c
===================================================================
RCS file: /fetish/cu/src/tail.c,v
retrieving revision 1.241
diff -p -u -r1.241 tail.c
--- src/tail.c  22 Aug 2005 10:31:17 -0000      1.241
+++ src/tail.c  16 Sep 2005 07:21:13 -0000
@@ -40,6 +40,7 @@
 #include "posixver.h"
 #include "quote.h"
 #include "safe-read.h"
+#include "stat-time.h"
 #include "xnanosleep.h"
 #include "xstrtol.h"
 #include "xstrtod.h"
@@ -327,8 +328,7 @@ record_open_fd (struct File_spec *f, int
 {
   f->fd = fd;
   f->size = size;
-  f->mtime.tv_sec = st->st_mtime;
-  f->mtime.tv_nsec = TIMESPEC_NS (st->st_mtim);
+  f->mtime = get_stat_mtime (st);
   f->dev = st->st_dev;
   f->ino = st->st_ino;
   f->mode = st->st_mode;
@@ -1039,10 +1039,9 @@ tail_forever (struct File_spec *f, int n
                  continue;
                }
 
-             if ((! S_ISREG (stats.st_mode) || f[i].size == stats.st_size)
-                 && f[i].mtime.tv_sec == stats.st_mtime
-                 && f[i].mtime.tv_nsec == TIMESPEC_NS (stats.st_mtim)
-                 && f[i].mode == stats.st_mode)
+             if (f[i].mode == stats.st_mode
+                 && (! S_ISREG (stats.st_mode) || f[i].size == stats.st_size)
+                 && timespec_cmp (f[i].mtime, get_stat_mtime (&stats)) == 0)
                {
                  if ((max_n_unchanged_stats_between_opens
                       <= f[i].n_unchanged_stats++)
@@ -1057,8 +1056,7 @@ tail_forever (struct File_spec *f, int n
              /* This file has changed.  Print out what we can, and
                 then keep looping.  */
 
-             f[i].mtime.tv_sec = stats.st_mtime;
-             f[i].mtime.tv_nsec = TIMESPEC_NS (stats.st_mtim);
+             f[i].mtime = get_stat_mtime (&stats);
              f[i].mode = stats.st_mode;
 
              /* reset counter */
Index: src/test.c
===================================================================
RCS file: /fetish/cu/src/test.c,v
retrieving revision 1.123
diff -p -u -r1.123 test.c
--- src/test.c  23 Aug 2005 15:28:22 -0000      1.123
+++ src/test.c  16 Sep 2005 07:21:13 -0000
@@ -45,6 +45,7 @@
 #include "euidaccess.h"
 #include "inttostr.h"
 #include "quote.h"
+#include "stat-time.h"
 #include "strnumcmp.h"
 
 #if HAVE_SYS_PARAM_H
@@ -159,20 +160,19 @@ find_int (char const *string)
   test_syntax_error (_("invalid integer %s\n"), quote (string));
 }
 
-/* Find the modification time of FILE, and stuff it into *AGE.
-   If the timestamp has a nonoseconds part, stuff that into *NS;
-   otherwise stuff zero into *NS.
+/* Find the modification time of FILE, and stuff it into *MTIME.
    Return true if successful.  */
 static bool
-age_of (char const *filename, time_t *age, long *ns)
+get_mtime (char const *filename, struct timespec *mtime)
 {
   struct stat finfo;
   bool ok = (stat (filename, &finfo) == 0);
+#ifdef lint
+  static struct timespec const zero;
+  *mtime = zero;
+#endif
   if (ok)
-    {
-      *age = finfo.st_mtime;
-      *ns = TIMESPEC_NS (finfo.st_mtim);
-    }
+    *mtime = get_stat_mtime (&finfo);
   return ok;
 }
 
@@ -322,20 +322,14 @@ binary_operator (bool l_is_l)
          if (argv[op][2] == 't' && !argv[op][3])
            {
              /* nt - newer than */
-             time_t lt IF_LINT (= 0);
-             time_t rt IF_LINT (= 0);
-             long l_ns IF_LINT (= 0);
-             long r_ns IF_LINT (= 0);
+             struct timespec lt, rt;
              bool le, re;
              pos += 3;
              if (l_is_l | r_is_l)
                test_syntax_error (_("-nt does not accept -l\n"), NULL);
-             le = age_of (argv[op - 1], &lt, &l_ns);
-             re = age_of (argv[op + 1], &rt, &r_ns);
-             if (le && re && (rt == lt))
-               return l_ns > r_ns;
-             else
-               return le > re || (le && lt > rt);
+             le = get_mtime (argv[op - 1], &lt);
+             re = get_mtime (argv[op + 1], &rt);
+             return le && (!re || timespec_cmp (lt, rt) > 0);
            }
          break;
 
@@ -357,20 +351,14 @@ binary_operator (bool l_is_l)
          if ('t' == argv[op][2] && '\000' == argv[op][3])
            {
              /* ot - older than */
-             time_t lt IF_LINT (= 0);
-             time_t rt IF_LINT (= 0);
-             long l_ns IF_LINT (= 0);
-             long r_ns IF_LINT (= 0);
+             struct timespec lt, rt;
              bool le, re;
              pos += 3;
              if (l_is_l | r_is_l)
                test_syntax_error (_("-ot does not accept -l\n"), NULL);
-             le = age_of (argv[op - 1], &lt, &l_ns);
-             re = age_of (argv[op + 1], &rt, &r_ns);
-             if (le && re && (lt == rt))
-               return l_ns < r_ns;
-             else
-               return le < re || (re && lt < rt);
+             le = get_mtime (argv[op - 1], &lt);
+             re = get_mtime (argv[op + 1], &rt);
+             return re && (!le || timespec_cmp (lt, rt) < 0);
            }
          break;
        }
Index: src/touch.c
===================================================================
RCS file: /fetish/cu/src/touch.c,v
retrieving revision 1.133
diff -p -u -r1.133 touch.c
--- src/touch.c 14 Aug 2005 14:18:07 -0000      1.133
+++ src/touch.c 16 Sep 2005 07:21:13 -0000
@@ -32,6 +32,7 @@
 #include "posixver.h"
 #include "quote.h"
 #include "safe-read.h"
+#include "stat-time.h"
 #include "utimens.h"
 
 /* The official name of this program (e.g., no `g' prefix).  */
@@ -170,22 +171,12 @@ touch (const char *file)
     }
   else
     {
-      if (change_times & CH_ATIME)
-       timespec[0] = newtime[0];
-      else
-       {
-         timespec[0].tv_sec = sbuf.st_atime;
-         timespec[0].tv_nsec = TIMESPEC_NS (sbuf.st_atim);
-       }
-
-      if (change_times & CH_MTIME)
-       timespec[1] = newtime[1];
-      else
-       {
-         timespec[1].tv_sec = sbuf.st_mtime;
-         timespec[1].tv_nsec = TIMESPEC_NS (sbuf.st_mtim);
-       }
-
+      timespec[0] = (change_times & CH_ATIME
+                    ? newtime[0]
+                    : get_stat_atime (&sbuf));
+      timespec[1] = (change_times & CH_MTIME
+                    ? newtime[1]
+                    : get_stat_mtime (&sbuf));
       t = timespec;
     }
 
@@ -342,10 +333,8 @@ main (int argc, char **argv)
       if (stat (ref_file, &ref_stats))
        error (EXIT_FAILURE, errno,
               _("failed to get attributes of %s"), quote (ref_file));
-      newtime[0].tv_sec = ref_stats.st_atime;
-      newtime[0].tv_nsec = TIMESPEC_NS (ref_stats.st_atim);
-      newtime[1].tv_sec = ref_stats.st_mtime;
-      newtime[1].tv_nsec = TIMESPEC_NS (ref_stats.st_mtim);
+      newtime[0] = get_stat_atime (&ref_stats);
+      newtime[1] = get_stat_mtime (&ref_stats);
       date_set = true;
       if (flex_date)
        {
--- /dev/null   2005-06-27 15:40:05.000000000 -0700
+++ lib/stat-time.h     2005-09-15 23:20:36.000000000 -0700
@@ -0,0 +1,178 @@
+/* stat-related time functions.
+
+   Copyright (C) 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert.  */
+
+#ifndef STAT_TIME_H
+#define STAT_TIME_H 1
+
+#include "timespec.h"
+
+/* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type
+   struct timespec, if available.  If not, then STAT_TIMESPEC_NS (ST,
+   ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST,
+   if available.  ST_XTIM can be st_atim, st_ctim, or st_mtim for
+   access, status change, or data modification time, respectively.
+
+   These macros are private to stat-time.h.  */
+#if defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
+#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
+# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
+#elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
+# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
+#elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
+# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
+#endif
+
+/* Return the nanosecond component of *ST's access time.  */
+static inline long int
+get_stat_atime_ns (struct stat const *st)
+{
+# if defined STAT_TIMESPEC
+  return STAT_TIMESPEC (st, st_atim).tv_nsec;
+# elif defined STAT_TIMESPEC_NS
+  return STAT_TIMESPEC_NS (st, st_atim);
+# elif defined HAVE_STRUCT_STAT_ST_SPARE1
+  return st->st_spare1 * 1000;
+# else
+  return 0;
+# endif
+}
+
+/* Return the nanosecond component of *ST's status change time.  */
+static inline long int
+get_stat_ctime_ns (struct stat const *st)
+{
+# if defined STAT_TIMESPEC
+  return STAT_TIMESPEC (st, st_ctim).tv_nsec;
+# elif defined STAT_TIMESPEC_NS
+  return STAT_TIMESPEC_NS (st, st_ctim);
+# elif defined HAVE_STRUCT_STAT_ST_SPARE1
+  return st->st_spare3 * 1000;
+# else
+  return 0;
+# endif
+}
+
+/* Return the nanosecond component of *ST's data modification time.  */
+static inline long int
+get_stat_mtime_ns (struct stat const *st)
+{
+# if defined STAT_TIMESPEC
+  return STAT_TIMESPEC (st, st_mtim).tv_nsec;
+# elif defined STAT_TIMESPEC_NS
+  return STAT_TIMESPEC_NS (st, st_mtim);
+# elif defined HAVE_STRUCT_STAT_ST_SPARE1
+  return st->st_spare2 * 1000;
+# else
+  return 0;
+# endif
+}
+
+/* Return *ST's access time.  */
+static inline struct timespec
+get_stat_atime (struct stat const *st)
+{
+#ifdef STAT_TIMESPEC
+  return STAT_TIMESPEC (st, st_atim);
+#else
+  struct timespec t;
+  t.tv_sec = st->st_atime;
+  t.tv_nsec = get_stat_atime_ns (st);
+  return t;
+#endif
+}
+
+/* Return *ST's status change time.  */
+static inline struct timespec
+get_stat_ctime (struct stat const *st)
+{
+#ifdef STAT_TIMESPEC
+  return STAT_TIMESPEC (st, st_ctim);
+#else
+  struct timespec t;
+  t.tv_sec = st->st_ctime;
+  t.tv_nsec = get_stat_ctime_ns (st);
+  return t;
+#endif
+}
+
+/* Return *ST's data modification time.  */
+static inline struct timespec
+get_stat_mtime (struct stat const *st)
+{
+#ifdef STAT_TIMESPEC
+  return STAT_TIMESPEC (st, st_mtim);
+#else
+  struct timespec t;
+  t.tv_sec = st->st_mtime;
+  t.tv_nsec = get_stat_mtime_ns (st);
+  return t;
+#endif
+}
+
+/* Set *ST's access time.  */
+static inline void
+set_stat_atime (struct stat *st, struct timespec t)
+{
+#ifdef STAT_TIMESPEC
+  STAT_TIMESPEC (st, st_atim) = t;
+#else
+  st->st_atime = t.tv_sec;
+# if defined STAT_TIMESPEC_NS
+  STAT_TIMESPEC_NS (st, st_atim) = t.tv_nsec;
+# elif defined HAVE_STRUCT_STAT_ST_SPARE1
+  st->st_spare1 = t.tv_nsec / 1000;
+# endif
+#endif
+}
+
+/* Set *ST's status change time.  */
+static inline void
+set_stat_ctime (struct stat *st, struct timespec t)
+{
+#ifdef STAT_TIMESPEC
+  STAT_TIMESPEC (st, st_ctim) = t;
+#else
+  st->st_ctime = t.tv_sec;
+# if defined STAT_TIMESPEC_NS
+  STAT_TIMESPEC_NS (st, st_ctim) = t.tv_nsec;
+# elif defined HAVE_STRUCT_STAT_ST_SPARE1
+  st->st_spare1 = t.tv_nsec / 1000;
+# endif
+#endif
+}
+
+/* Set *ST's data modification time.  */
+static inline void
+set_stat_mtime (struct stat *st, struct timespec t)
+{
+#ifdef STAT_TIMESPEC
+  STAT_TIMESPEC (st, st_mtim) = t;
+#else
+  st->st_mtime = t.tv_sec;
+# if defined STAT_TIMESPEC_NS
+  STAT_TIMESPEC_NS (st, st_mtim) = t.tv_nsec;
+# elif defined HAVE_STRUCT_STAT_ST_SPARE1
+  st->st_spare1 = t.tv_nsec / 1000;
+# endif
+#endif
+}
+
+#endif
--- /dev/null   2005-06-27 15:40:05.000000000 -0700
+++ m4/stat-time.m4     2005-08-14 23:46:04.000000000 -0700
@@ -0,0 +1,39 @@
+# Checks for stat-related time functions.
+
+# Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+# st_atim.tv_nsec - Linux, Solaris
+# st_atimespec.tv_nsec - FreeBSD, if ! defined _POSIX_SOURCE
+# st_atimensec - FreeBSD, if defined _POSIX_SOURCE
+# st_atim.st__tim.tv_nsec - UnixWare (at least 2.1.2 through 7.1)
+# st_spare1 - Cygwin?
+
+AC_DEFUN([gl_STAT_TIME],
+[
+  AC_LIBSOURCES([stat-time.h])
+
+  AC_REQUIRE([AC_C_INLINE])
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+  AC_CHECK_MEMBERS([struct stat.st_atim.tv_nsec], [],
+    [AC_CHECK_MEMBERS([struct stat.st_atimespec.tv_nsec], [],
+       [AC_CHECK_MEMBERS([struct stat.st_atimensec], [],
+         [AC_CHECK_MEMBERS([struct stat.st_atim.st__tim.tv_nsec], [],
+            [AC_CHECK_MEMBERS([struct stat.st_spare1], [],
+               [],
+               [#include <sys/types.h>
+                #include <sys/stat.h>])],
+            [#include <sys/types.h>
+             #include <sys/stat.h>])],
+         [#include <sys/types.h>
+          #include <sys/stat.h>])],
+       [#include <sys/types.h>
+       #include <sys/stat.h>])],
+    [#include <sys/types.h>
+     #include <sys/stat.h>])
+])




reply via email to

[Prev in Thread] Current Thread [Next in Thread]