Mercurial > hg > octave-kai > gnulib-hg
diff lib/stat-time.h @ 8565:c49cf515502f
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.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Tue, 27 Mar 2007 11:01:11 +0000 |
parents | ca249819379f |
children | f7fc3652bfc5 |
line wrap: on
line diff
--- 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 @@ # 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 @@ #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