summaryrefslogtreecommitdiff
path: root/lib/stat-time.h
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2017-11-25 22:28:31 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2017-11-25 22:48:09 -0800
commit8be3aee2813f528b02bc913ca4d79e34e72b1754 (patch)
treeaf1e8e35cedfe601076eade046a1a12303b93e84 /lib/stat-time.h
parent265cee553f9d59a989d92e28865f6cc6fc02dcc9 (diff)
downloademacs-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.h45
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