summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2007-03-27 11:01:11 +0000
committerBruno Haible <bruno@clisp.org>2007-03-27 11:01:11 +0000
commit735c00a2f3a5ce7aaec8517f5438ce37b48a936c (patch)
tree41cc9b8d0367ee93915f67063e82eb6d3769b010 /lib
parent6997174ab598e752b1a66d9928aaae871c1700db (diff)
downloadgnulib-735c00a2f3a5ce7aaec8517f5438ce37b48a936c.tar.gz
2007-03-27 Bruno Haible <bruno@clisp.org>
* lib/stat-time.h: Include <sys/stat.h>. 2007-03-27 James Youngman <jay@gnu.org> * lib/stat-time.h (get_stat_birthtime): New function for retrieving st_birthtime as provided by UFS2 (hence *BSD). * m4/stat-time.m4 (gl_STAT_BIRTHTIME): Probe for st_birthtime and its variants. * modules/stat-time (configure.ac): call gl_STAT_BIRTHTIME. * modules/stat-time-test: New file. * tests/test-stat-time.c: New test, devised by Bruno Haible.
Diffstat (limited to 'lib')
-rw-r--r--lib/stat-time.h95
1 files changed, 95 insertions, 0 deletions
diff --git a/lib/stat-time.h b/lib/stat-time.h
index 5fd18c1fac..50e907c5ad 100644
--- a/lib/stat-time.h
+++ b/lib/stat-time.h
@@ -21,6 +21,7 @@
#ifndef STAT_TIME_H
#define STAT_TIME_H 1
+#include <sys/stat.h>
#include <time.h>
/* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type
@@ -44,6 +45,13 @@
# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
#endif
+#if defined HAVE_STRUCT_STAT_ST_BIRTHTIME || defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC || defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC || defined HAVE_STRUCT_STAT_ST_SPARE4
+# define USE_BIRTHTIME 1
+#else
+# undef USE_BIRTHTIME
+#endif
+
+
/* Return the nanosecond component of *ST's access time. */
static inline long int
get_stat_atime_ns (struct stat const *st)
@@ -89,6 +97,28 @@ get_stat_mtime_ns (struct stat const *st)
# endif
}
+/* Return the nanosecond component of *ST's birth time. */
+static inline long int
+get_stat_birthtime_ns (struct stat const *st)
+{
+# if defined USE_BIRTHTIME
+# if defined STAT_TIMESPEC && defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
+ return STAT_TIMESPEC (st, st_birthtim).tv_nsec;
+# elif defined STAT_TIMESPEC_NS && defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_SEC
+ return STAT_TIMESPEC_NS (st, st_birthtim);
+# elif defined HAVE_STRUCT_STAT_ST_SPARE4
+ /* Cygwin, without __CYGWIN_USE_BIG_TYPES__ */
+ return st->st_spare4[1] * 1000L;
+# else
+ /* Birthtime is available, but not at nanosecond resolution. */
+ return 0;
+# endif
+# else
+ /* Birthtime is not available, so indicate this in the returned value. */
+ return 0;
+# endif
+}
+
/* Return *ST's access time. */
static inline struct timespec
get_stat_atime (struct stat const *st)
@@ -131,4 +161,69 @@ get_stat_mtime (struct stat const *st)
#endif
}
+/* Return *ST's birth time, if available, in *PTS. A nonzero value is
+ * returned if the stat structure appears to indicate that the
+ * timestamp is available.
+ *
+ * The return value of this function does not reliably indicate that the
+ * returned data is valid; see the comments within the body of the
+ * function for an explanation.
+ */
+static inline int
+get_stat_birthtime (struct stat const *st,
+ struct timespec *pts)
+{
+#if defined USE_BIRTHTIME
+# ifdef STAT_TIMESPEC
+ *pts = STAT_TIMESPEC (st, st_birthtim);
+# else
+ struct timespec t;
+ pts->tv_sec = st->st_birthtime;
+ pts->tv_nsec = get_stat_birthtime_ns (st);
+# endif
+
+ /* NetBSD sometimes signals the absence of knowledge of the file's
+ * birth time by using zero. We indicate we don't know, by
+ * returning 0 from this function when that happens. This is
+ * slightly problematic since (time_t)0 is otherwise a valid, albeit
+ * unlikely, timestamp.
+ *
+ * NetBSD sometimes returns 0 for unknown values (for example on
+ * ffs) and sometimes begative values for tv_nsec (for example on
+ * NFS). For some filesystems (e.g. msdos) NetBSD also appears to
+ * fail to update the st_birthtime member at all, and just leaves in
+ * there whatever junk existed int he uninitialised stat structure
+ * the caller provided. Therefore, callers are advised to initialise
+ * the tv_nsec number to a negative value before they call stat in
+ * order to detect this problem.
+ */
+ if (pts->tv_sec == (time_t)0)
+ {
+ return 0; /* result probably invalid, see above. */
+ }
+ else
+ {
+ /* Sometimes NetBSD returns junk in the birth time fields, so
+ * do a simple range check on the data, and return 0 to indicate
+ * that the data is invalid if it just looks wrong.
+ */
+ return (pts->tv_nsec >= 0) && (pts->tv_nsec <= 1000000000);
+ }
+#elif (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
+ /* Woe32 native platforms (mingw, msvc, but not Cygwin) put the
+ * "file creation time" in st_ctime (!). See for example the
+ * article
+ * <http://msdn2.microsoft.com/de-de/library/14h5k7ff(VS.80).aspx>
+ */
+ pts->tv_sec = st->st_ctime;
+ pts->tv_nsec = 0;
+ return 1; /* result is valid */
+#else
+ /* Birth time not supported. */
+ pts->tv_sec = 0;
+ pts->tv_nsec = 0;
+ return 0; /* result is not valid */
+#endif
+}
+
#endif