diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2017-11-25 22:28:31 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2017-11-25 22:48:09 -0800 |
commit | 8be3aee2813f528b02bc913ca4d79e34e72b1754 (patch) | |
tree | af1e8e35cedfe601076eade046a1a12303b93e84 /lib/stat-time.h | |
parent | 265cee553f9d59a989d92e28865f6cc6fc02dcc9 (diff) | |
download | emacs-8be3aee2813f528b02bc913ca4d79e34e72b1754.tar.gz |
Merge from Gnulib
This incorporates:
2017-11-23 stat: work around Solaris bug with tv_nsec < 0
2017-11-12 maint: shorten https://lists.gnu.org/archive/html/... links
* build-aux/config.sub, doc/misc/texinfo.tex, lib/allocator.h:
* lib/fstatat.c, lib/intprops.h, lib/lstat.c, lib/signal.in.h:
* lib/stat-time.h, lib/stdio-impl.h, lib/stdio.in.h:
* lib/timespec.h, m4/alloca.m4, m4/extern-inline.m4:
* m4/faccessat.m4, m4/fstatat.m4, m4/gnulib-common.m4:
* m4/lstat.m4, m4/std-gnu11.m4, m4/sys_types_h.m4:
* m4/vararrays.m4:
Copy from Gnulib.
Diffstat (limited to 'lib/stat-time.h')
-rw-r--r-- | lib/stat-time.h | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/stat-time.h b/lib/stat-time.h index 47a3bf8f21e..1cf821992ed 100644 --- a/lib/stat-time.h +++ b/lib/stat-time.h @@ -20,6 +20,10 @@ #ifndef STAT_TIME_H #define STAT_TIME_H 1 +#include "intprops.h" + +#include <errno.h> +#include <stddef.h> #include <sys/stat.h> #include <time.h> @@ -202,6 +206,47 @@ get_stat_birthtime (struct stat const *st) return t; } +/* If a stat-like function returned RESULT, normalize the timestamps + in *ST, in case this platform suffers from the Solaris 11 bug where + tv_nsec might be negative. Return the adjusted RESULT, setting + errno to EOVERFLOW if normalization overflowed. This function + is intended to be private to this .h file. */ +_GL_STAT_TIME_INLINE int +stat_time_normalize (int result, struct stat *st) +{ +#if defined __sun && defined STAT_TIMESPEC + if (result == 0) + { + long int timespec_resolution = 1000000000; + short int const ts_off[] = { offsetof (struct stat, st_atim), + offsetof (struct stat, st_mtim), + offsetof (struct stat, st_ctim) }; + int i; + for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++) + { + struct timespec *ts = (struct timespec *) ((char *) st + ts_off[i]); + long int q = ts->tv_nsec / timespec_resolution; + long int r = ts->tv_nsec % timespec_resolution; + if (r < 0) + { + r += timespec_resolution; + q--; + } + ts->tv_nsec = r; + /* Overflow is possible, as Solaris 11 stat can yield + tv_sec == TYPE_MINIMUM (time_t) && tv_nsec == -1000000000. + INT_ADD_WRAPV is OK, since time_t is signed on Solaris. */ + if (INT_ADD_WRAPV (q, ts->tv_sec, &ts->tv_sec)) + { + errno = EOVERFLOW; + return -1; + } + } + } +#endif + return result; +} + #ifdef __cplusplus } #endif |