aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPaul Eggert2017-05-01 15:33:06 -0700
committerPaul Eggert2017-05-01 15:33:26 -0700
commit634d0a907ff7ba5901dfe3624e58d718f3f37cec (patch)
tree6bf86cf04d8b28a79693df9cdef1063c9b06ca76 /lib
parent16b49e214ad828de29ceb57ad1b443eece9bba03 (diff)
downloademacs-634d0a907ff7ba5901dfe3624e58d718f3f37cec.tar.gz
emacs-634d0a907ff7ba5901dfe3624e58d718f3f37cec.zip
Merge from gnulib
This incorporates: 2017-05-01 New module 'localtime-buffer' 2017-04-30 utimens: Add support for native Windows * admin/merge-gnulib (AVOIDED_MODULES): Add tzset. * configure.ac (tzset): No need for Emacs itself to check now. * lib/gettimeofday.c, lib/time.in.h, lib/time_rz.c, lib/utimens.c: * m4/gettimeofday.m4, m4/time_h.m4, m4/time_rz.m4: Copy from gnulib. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * lib/localtime-buffer.c, lib/localtime-buffer.h: * m4/localtime-buffer.m4: New files, copied from gnulib. * src/editfns.c (init_editfns): Assume tzset is callable.
Diffstat (limited to 'lib')
-rw-r--r--lib/gettimeofday.c73
-rw-r--r--lib/gnulib.mk.in23
-rw-r--r--lib/localtime-buffer.c58
-rw-r--r--lib/localtime-buffer.h27
-rw-r--r--lib/time.in.h22
-rw-r--r--lib/time_rz.c4
-rw-r--r--lib/utimens.c82
7 files changed, 214 insertions, 75 deletions
diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c
index 86f1a8c1d28..1039f77d182 100644
--- a/lib/gettimeofday.c
+++ b/lib/gettimeofday.c
@@ -29,72 +29,7 @@
29# include <windows.h> 29# include <windows.h>
30#endif 30#endif
31 31
32#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME 32#include "localtime-buffer.h"
33
34/* Work around the bug in some systems whereby gettimeofday clobbers
35 the static buffer that localtime uses for its return value. The
36 gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has
37 this problem. The tzset replacement is necessary for at least
38 Solaris 2.5, 2.5.1, and 2.6. */
39
40static struct tm tm_zero_buffer;
41static struct tm *localtime_buffer_addr = &tm_zero_buffer;
42
43# undef localtime
44extern struct tm *localtime (time_t const *);
45
46# undef gmtime
47extern struct tm *gmtime (time_t const *);
48
49/* This is a wrapper for localtime. It is used only on systems for which
50 gettimeofday clobbers the static buffer used for localtime's result.
51
52 On the first call, record the address of the static buffer that
53 localtime uses for its result. */
54
55struct tm *
56rpl_localtime (time_t const *timep)
57{
58 struct tm *tm = localtime (timep);
59
60 if (localtime_buffer_addr == &tm_zero_buffer)
61 localtime_buffer_addr = tm;
62
63 return tm;
64}
65
66/* Same as above, since gmtime and localtime use the same buffer. */
67struct tm *
68rpl_gmtime (time_t const *timep)
69{
70 struct tm *tm = gmtime (timep);
71
72 if (localtime_buffer_addr == &tm_zero_buffer)
73 localtime_buffer_addr = tm;
74
75 return tm;
76}
77
78#endif /* GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME */
79
80#if TZSET_CLOBBERS_LOCALTIME
81
82# undef tzset
83extern void tzset (void);
84
85/* This is a wrapper for tzset, for systems on which tzset may clobber
86 the static buffer used for localtime's result. */
87void
88rpl_tzset (void)
89{
90 /* Save and restore the contents of the buffer used for localtime's
91 result around the call to tzset. */
92 struct tm save = *localtime_buffer_addr;
93 tzset ();
94 *localtime_buffer_addr = save;
95}
96
97#endif
98 33
99#ifdef WINDOWS_NATIVE 34#ifdef WINDOWS_NATIVE
100 35
@@ -119,7 +54,11 @@ initialize (void)
119 54
120/* This is a wrapper for gettimeofday. It is used only on systems 55/* This is a wrapper for gettimeofday. It is used only on systems
121 that lack this function, or whose implementation of this function 56 that lack this function, or whose implementation of this function
122 causes problems. */ 57 causes problems.
58 Work around the bug in some systems whereby gettimeofday clobbers
59 the static buffer that localtime uses for its return value. The
60 gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has
61 this problem. */
123 62
124int 63int
125gettimeofday (struct timeval *restrict tv, void *restrict tz) 64gettimeofday (struct timeval *restrict tv, void *restrict tz)
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 59cdbdb847a..51ae1891244 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -21,7 +21,7 @@
21# the same distribution terms as the rest of that program. 21# the same distribution terms as the rest of that program.
22# 22#
23# Generated by gnulib-tool. 23# Generated by gnulib-tool.
24# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=unsetenv --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub update-copyright utimens vla warnings 24# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub update-copyright utimens vla warnings
25 25
26 26
27MOSTLYCLEANFILES += core *.stackdump 27MOSTLYCLEANFILES += core *.stackdump
@@ -307,6 +307,7 @@ GNULIB_TIME_R = @GNULIB_TIME_R@
307GNULIB_TIME_RZ = @GNULIB_TIME_RZ@ 307GNULIB_TIME_RZ = @GNULIB_TIME_RZ@
308GNULIB_TMPFILE = @GNULIB_TMPFILE@ 308GNULIB_TMPFILE = @GNULIB_TMPFILE@
309GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@ 309GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@
310GNULIB_TZSET = @GNULIB_TZSET@
310GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@ 311GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@
311GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@ 312GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@
312GNULIB_UNLINK = @GNULIB_UNLINK@ 313GNULIB_UNLINK = @GNULIB_UNLINK@
@@ -504,6 +505,7 @@ HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@
504HAVE_TIMEGM = @HAVE_TIMEGM@ 505HAVE_TIMEGM = @HAVE_TIMEGM@
505HAVE_TIMEZONE_T = @HAVE_TIMEZONE_T@ 506HAVE_TIMEZONE_T = @HAVE_TIMEZONE_T@
506HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ 507HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@
508HAVE_TZSET = @HAVE_TZSET@
507HAVE_UNISTD_H = @HAVE_UNISTD_H@ 509HAVE_UNISTD_H = @HAVE_UNISTD_H@
508HAVE_UNLINKAT = @HAVE_UNLINKAT@ 510HAVE_UNLINKAT = @HAVE_UNLINKAT@
509HAVE_UNLOCKPT = @HAVE_UNLOCKPT@ 511HAVE_UNLOCKPT = @HAVE_UNLOCKPT@
@@ -780,6 +782,7 @@ REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@
780REPLACE_TIMEGM = @REPLACE_TIMEGM@ 782REPLACE_TIMEGM = @REPLACE_TIMEGM@
781REPLACE_TMPFILE = @REPLACE_TMPFILE@ 783REPLACE_TMPFILE = @REPLACE_TMPFILE@
782REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@ 784REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@
785REPLACE_TZSET = @REPLACE_TZSET@
783REPLACE_UNLINK = @REPLACE_UNLINK@ 786REPLACE_UNLINK = @REPLACE_UNLINK@
784REPLACE_UNLINKAT = @REPLACE_UNLINKAT@ 787REPLACE_UNLINKAT = @REPLACE_UNLINKAT@
785REPLACE_UNSETENV = @REPLACE_UNSETENV@ 788REPLACE_UNSETENV = @REPLACE_UNSETENV@
@@ -879,6 +882,7 @@ gamedir = @gamedir@
879gamegroup = @gamegroup@ 882gamegroup = @gamegroup@
880gameuser = @gameuser@ 883gameuser = @gameuser@
881gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7 = @gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7@ 884gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7 = @gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7@
885gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9 = @gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9@
882gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b = @gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b@ 886gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b = @gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b@
883gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31 = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31@ 887gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31 = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31@
884gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c@ 888gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c@
@@ -1700,6 +1704,19 @@ EXTRA_DIST += limits.in.h
1700endif 1704endif
1701## end gnulib module limits-h 1705## end gnulib module limits-h
1702 1706
1707## begin gnulib module localtime-buffer
1708ifeq (,$(OMIT_GNULIB_MODULE_localtime-buffer))
1709
1710ifneq (,$(gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9))
1711
1712endif
1713EXTRA_DIST += localtime-buffer.c localtime-buffer.h
1714
1715EXTRA_libgnu_a_SOURCES += localtime-buffer.c
1716
1717endif
1718## end gnulib module localtime-buffer
1719
1703## begin gnulib module lstat 1720## begin gnulib module lstat
1704ifeq (,$(OMIT_GNULIB_MODULE_lstat)) 1721ifeq (,$(OMIT_GNULIB_MODULE_lstat))
1705 1722
@@ -2707,7 +2724,6 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
2707 -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ 2724 -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
2708 -e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \ 2725 -e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \
2709 -e 's/@''GNULIB_CTIME''@/$(GNULIB_CTIME)/g' \ 2726 -e 's/@''GNULIB_CTIME''@/$(GNULIB_CTIME)/g' \
2710 -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \
2711 -e 's/@''GNULIB_LOCALTIME''@/$(GNULIB_LOCALTIME)/g' \ 2727 -e 's/@''GNULIB_LOCALTIME''@/$(GNULIB_LOCALTIME)/g' \
2712 -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \ 2728 -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \
2713 -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \ 2729 -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \
@@ -2716,11 +2732,13 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
2716 -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \ 2732 -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \
2717 -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \ 2733 -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \
2718 -e 's/@''GNULIB_TIME_RZ''@/$(GNULIB_TIME_RZ)/g' \ 2734 -e 's/@''GNULIB_TIME_RZ''@/$(GNULIB_TIME_RZ)/g' \
2735 -e 's/@''GNULIB_TZSET''@/$(GNULIB_TZSET)/g' \
2719 -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \ 2736 -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \
2720 -e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \ 2737 -e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \
2721 -e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \ 2738 -e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \
2722 -e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \ 2739 -e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \
2723 -e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \ 2740 -e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \
2741 -e 's|@''HAVE_TZSET''@|$(HAVE_TZSET)|g' \
2724 -e 's|@''REPLACE_CTIME''@|$(REPLACE_CTIME)|g' \ 2742 -e 's|@''REPLACE_CTIME''@|$(REPLACE_CTIME)|g' \
2725 -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \ 2743 -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \
2726 -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \ 2744 -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \
@@ -2729,6 +2747,7 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
2729 -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \ 2747 -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \
2730 -e 's|@''REPLACE_STRFTIME''@|$(REPLACE_STRFTIME)|g' \ 2748 -e 's|@''REPLACE_STRFTIME''@|$(REPLACE_STRFTIME)|g' \
2731 -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \ 2749 -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \
2750 -e 's|@''REPLACE_TZSET''@|$(REPLACE_TZSET)|g' \
2732 -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \ 2751 -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \
2733 -e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ 2752 -e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
2734 -e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ 2753 -e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
diff --git a/lib/localtime-buffer.c b/lib/localtime-buffer.c
new file mode 100644
index 00000000000..f84ad3e8238
--- /dev/null
+++ b/lib/localtime-buffer.c
@@ -0,0 +1,58 @@
1/* Provide access to the last buffer returned by localtime() or gmtime().
2
3 Copyright (C) 2001-2003, 2005-2007, 2009-2017 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>. */
17
18/* written by Jim Meyering */
19
20#include <config.h>
21
22/* Specification. */
23#include "localtime-buffer.h"
24
25#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME
26
27static struct tm tm_zero_buffer;
28struct tm *localtime_buffer_addr = &tm_zero_buffer;
29
30/* This is a wrapper for localtime.
31
32 On the first call, record the address of the static buffer that
33 localtime uses for its result. */
34
35struct tm *
36rpl_localtime (time_t const *timep)
37{
38 struct tm *tm = localtime (timep);
39
40 if (localtime_buffer_addr == &tm_zero_buffer)
41 localtime_buffer_addr = tm;
42
43 return tm;
44}
45
46/* Same as above, since gmtime and localtime use the same buffer. */
47struct tm *
48rpl_gmtime (time_t const *timep)
49{
50 struct tm *tm = gmtime (timep);
51
52 if (localtime_buffer_addr == &tm_zero_buffer)
53 localtime_buffer_addr = tm;
54
55 return tm;
56}
57
58#endif
diff --git a/lib/localtime-buffer.h b/lib/localtime-buffer.h
new file mode 100644
index 00000000000..483a579bda4
--- /dev/null
+++ b/lib/localtime-buffer.h
@@ -0,0 +1,27 @@
1/* Provide access to the last buffer returned by localtime() or gmtime().
2
3 Copyright (C) 2001-2003, 2005-2007, 2009-2017 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>. */
17
18/* written by Jim Meyering */
19
20#include <time.h>
21
22#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME
23
24/* The address of the last buffer returned by localtime() or gmtime(). */
25extern struct tm *localtime_buffer_addr;
26
27#endif
diff --git a/lib/time.in.h b/lib/time.in.h
index d2a0302f464..f0c7ef86667 100644
--- a/lib/time.in.h
+++ b/lib/time.in.h
@@ -120,6 +120,24 @@ _GL_CXXALIAS_SYS (nanosleep, int,
120_GL_CXXALIASWARN (nanosleep); 120_GL_CXXALIASWARN (nanosleep);
121# endif 121# endif
122 122
123/* Initialize time conversion information. */
124# if @GNULIB_TZSET@
125# if @REPLACE_TZSET@
126# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
127# undef tzset
128# define tzset rpl_tzset
129# endif
130_GL_FUNCDECL_RPL (tzset, void, (void));
131_GL_CXXALIAS_RPL (tzset, void, (void));
132# else
133# if ! @HAVE_TZSET@
134_GL_FUNCDECL_SYS (tzset, void, (void));
135# endif
136_GL_CXXALIAS_SYS (tzset, void, (void));
137# endif
138_GL_CXXALIASWARN (tzset);
139# endif
140
123/* Return the 'time_t' representation of TP and normalize TP. */ 141/* Return the 'time_t' representation of TP and normalize TP. */
124# if @GNULIB_MKTIME@ 142# if @GNULIB_MKTIME@
125# if @REPLACE_MKTIME@ 143# if @REPLACE_MKTIME@
@@ -187,7 +205,7 @@ _GL_CXXALIASWARN (gmtime_r);
187/* Convert TIMER to RESULT, assuming local time and UTC respectively. See 205/* Convert TIMER to RESULT, assuming local time and UTC respectively. See
188 <http://www.opengroup.org/susv3xsh/localtime.html> and 206 <http://www.opengroup.org/susv3xsh/localtime.html> and
189 <http://www.opengroup.org/susv3xsh/gmtime.html>. */ 207 <http://www.opengroup.org/susv3xsh/gmtime.html>. */
190# if @GNULIB_LOCALTIME@ || @GNULIB_GETTIMEOFDAY@ 208# if @GNULIB_LOCALTIME@ || @REPLACE_LOCALTIME@
191# if @REPLACE_LOCALTIME@ 209# if @REPLACE_LOCALTIME@
192# if !(defined __cplusplus && defined GNULIB_NAMESPACE) 210# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
193# undef localtime 211# undef localtime
@@ -202,7 +220,7 @@ _GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer));
202_GL_CXXALIASWARN (localtime); 220_GL_CXXALIASWARN (localtime);
203# endif 221# endif
204 222
205# if @GNULIB_GETTIMEOFDAY@ 223# if 0 || @REPLACE_GMTIME@
206# if @REPLACE_GMTIME@ 224# if @REPLACE_GMTIME@
207# if !(defined __cplusplus && defined GNULIB_NAMESPACE) 225# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
208# undef gmtime 226# undef gmtime
diff --git a/lib/time_rz.c b/lib/time_rz.c
index c41a8ef47ac..17bc11c20e9 100644
--- a/lib/time_rz.c
+++ b/lib/time_rz.c
@@ -40,10 +40,6 @@
40# define SIZE_MAX ((size_t) -1) 40# define SIZE_MAX ((size_t) -1)
41#endif 41#endif
42 42
43#if !HAVE_TZSET
44static void tzset (void) { }
45#endif
46
47/* The approximate size to use for small allocation requests. This is 43/* The approximate size to use for small allocation requests. This is
48 the largest "small" request for the GNU C library malloc. */ 44 the largest "small" request for the GNU C library malloc. */
49enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; 45enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
diff --git a/lib/utimens.c b/lib/utimens.c
index 3b451193350..0b3b8e2f3af 100644
--- a/lib/utimens.c
+++ b/lib/utimens.c
@@ -35,6 +35,12 @@
35#include "stat-time.h" 35#include "stat-time.h"
36#include "timespec.h" 36#include "timespec.h"
37 37
38#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
39# define WIN32_LEAN_AND_MEAN
40# include <windows.h>
41# include "msvc-nothrow.h"
42#endif
43
38/* Avoid recursion with rpl_futimens or rpl_utimensat. */ 44/* Avoid recursion with rpl_futimens or rpl_utimensat. */
39#undef futimens 45#undef futimens
40#undef utimensat 46#undef utimensat
@@ -271,6 +277,82 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
271 lutimensat_works_really = -1; 277 lutimensat_works_really = -1;
272#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */ 278#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
273 279
280#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
281 /* On native Windows, use SetFileTime(). See
282 <https://msdn.microsoft.com/en-us/library/ms724933.aspx>
283 <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */
284 if (0 <= fd)
285 {
286 HANDLE handle;
287 FILETIME current_time;
288 FILETIME last_access_time;
289 FILETIME last_write_time;
290
291 handle = (HANDLE) _get_osfhandle (fd);
292 if (handle == INVALID_HANDLE_VALUE)
293 {
294 errno = EBADF;
295 return -1;
296 }
297
298 if (ts == NULL || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW)
299 {
300 /* GetSystemTimeAsFileTime
301 <https://msdn.microsoft.com/en-us/library/ms724397.aspx>.
302 It would be overkill to use
303 GetSystemTimePreciseAsFileTime
304 <https://msdn.microsoft.com/en-us/library/hh706895.aspx>. */
305 GetSystemTimeAsFileTime (&current_time);
306 }
307
308 if (ts == NULL || ts[0].tv_nsec == UTIME_NOW)
309 {
310 last_access_time = current_time;
311 }
312 else if (ts[0].tv_nsec == UTIME_OMIT)
313 {
314 last_access_time.dwLowDateTime = 0;
315 last_access_time.dwHighDateTime = 0;
316 }
317 else
318 {
319 ULONGLONG time_since_16010101 =
320 (ULONGLONG) ts[0].tv_sec * 10000000 + ts[0].tv_nsec / 100 + 116444736000000000LL;
321 last_access_time.dwLowDateTime = (DWORD) time_since_16010101;
322 last_access_time.dwHighDateTime = time_since_16010101 >> 32;
323 }
324
325 if (ts == NULL || ts[1].tv_nsec == UTIME_NOW)
326 {
327 last_write_time = current_time;
328 }
329 else if (ts[1].tv_nsec == UTIME_OMIT)
330 {
331 last_write_time.dwLowDateTime = 0;
332 last_write_time.dwHighDateTime = 0;
333 }
334 else
335 {
336 ULONGLONG time_since_16010101 =
337 (ULONGLONG) ts[1].tv_sec * 10000000 + ts[1].tv_nsec / 100 + 116444736000000000LL;
338 last_write_time.dwLowDateTime = (DWORD) time_since_16010101;
339 last_write_time.dwHighDateTime = time_since_16010101 >> 32;
340 }
341
342 if (SetFileTime (handle, NULL, &last_access_time, &last_write_time))
343 return 0;
344 else
345 {
346 #if 0
347 DWORD sft_error = GetLastError ();
348 fprintf (stderr, "utime SetFileTime error 0x%x\n", (unsigned int) sft_error);
349 #endif
350 errno = EINVAL;
351 return -1;
352 }
353 }
354#endif
355
274 /* The platform lacks an interface to set file timestamps with 356 /* The platform lacks an interface to set file timestamps with
275 nanosecond resolution, so do the best we can, discarding any 357 nanosecond resolution, so do the best we can, discarding any
276 fractional part of the timestamp. */ 358 fractional part of the timestamp. */