bug-gnulib
[Top][All Lists]
Advanced

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

new module stat-time, to ease access to sub-second file time stamps


From: Paul Eggert
Subject: new module stat-time, to ease access to sub-second file time stamps
Date: Thu, 15 Sep 2005 23:56:45 -0700
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

I installed the following patch to clean up the timespec module, which
had some stat-related stuff in it that (1) really belonged in a
separate module, and (2) did not support sub-second file time stamp
resolution on several operating systems, e.g., OpenBSD.

Much of the new code is stolen from GNU tar.  I have tested these
changes with (modified) GNU tar and coreutils, and will update tar and
coreutils soon to incorporate these changes.

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

        * MODULES.html.sh (File system functions): Add stat-time.
        * 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.
        * 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.
        * modules/stat-time: New file.
        * modules/timespec (Files): Remove m4/st_mtim.m4; this
        is now done in a different way, by the stat-time module.

Index: MODULES.html.sh
===================================================================
RCS file: /cvsroot/gnulib/gnulib/MODULES.html.sh,v
retrieving revision 1.106
diff -p -u -r1.106 MODULES.html.sh
--- MODULES.html.sh     25 Aug 2005 12:36:01 -0000      1.106
+++ MODULES.html.sh     16 Sep 2005 06:48:17 -0000
@@ -1849,6 +1849,7 @@ func_all_modules ()
   func_module same
   func_module save-cwd
   func_module savedir
+  func_module stat-time
   func_module unlinkdir
   func_module utimecmp
   func_module utimens
Index: lib/timespec.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/timespec.h,v
retrieving revision 1.5
diff -p -u -r1.5 timespec.h
--- lib/timespec.h      14 May 2005 06:03:58 -0000      1.5
+++ lib/timespec.h      16 Sep 2005 06:48:18 -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: m4/timespec.m4
===================================================================
RCS file: /cvsroot/gnulib/gnulib/m4/timespec.m4,v
retrieving revision 1.10
diff -p -u -r1.10 timespec.m4
--- m4/timespec.m4      21 Mar 2005 22:06:27 -0000      1.10
+++ m4/timespec.m4      16 Sep 2005 06:48:18 -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: modules/timespec
===================================================================
RCS file: /cvsroot/gnulib/gnulib/modules/timespec,v
retrieving revision 1.6
diff -p -u -r1.6 timespec
--- modules/timespec    21 Mar 2005 22:07:25 -0000      1.6
+++ modules/timespec    16 Sep 2005 06:48:18 -0000
@@ -3,7 +3,6 @@ struct timespec.
 
 Files:
 lib/timespec.h
-m4/st_mtim.m4
 m4/timespec.m4
 
 Depends-on:
--- /dev/null   2005-06-27 15:40:05.000000000 -0700
+++ modules/stat-time   2005-09-15 22:45:47.000000000 -0700
@@ -0,0 +1,23 @@
+Description:
+stat-related time functions
+
+Files:
+lib/stat-time.h
+m4/stat-time.m4
+
+Depends-on:
+timespec
+
+configure.ac:
+gl_STAT_TIME
+
+Makefile.am:
+
+Include:
+"stat-time.h"
+
+License:
+GPL
+
+Maintainer:
+Paul Eggert and Jim Meyering
--- /dev/null   2005-06-27 15:40:05.000000000 -0700
+++ m4/stat-time.m4     2005-09-15 22:39:57.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>])
+])
--- /dev/null   2005-06-27 15:40:05.000000000 -0700
+++ lib/stat-time.h     2005-09-15 23:21:44.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




reply via email to

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