[Top][All Lists]
[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 (×pec);
- 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], <, &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], <);
+ 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], <, &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], <);
+ 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>])
+])
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- imported sub-second file time stamp improvements from tar via gnulib,
Paul Eggert <=