aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPaul Eggert2012-06-22 14:26:37 -0700
committerPaul Eggert2012-06-22 14:26:37 -0700
commitc8fff8630133fea7c4e279458d10d825e5028c62 (patch)
treef8b8261fdf3596e1306a3d072e13ec572c9e3e65 /lib
parent36cec983d4e680e28e7066fda505910cd549f509 (diff)
downloademacs-c8fff8630133fea7c4e279458d10d825e5028c62.tar.gz
emacs-c8fff8630133fea7c4e279458d10d825e5028c62.zip
Add gnulib files to support higher-resolution time stamps.
Fixes: debbugs:9000
Diffstat (limited to 'lib')
-rw-r--r--lib/dtotimespec.c69
-rw-r--r--lib/gettime.c48
-rw-r--r--lib/gettimeofday.c154
-rw-r--r--lib/pselect.c76
-rw-r--r--lib/stat-time.h189
-rw-r--r--lib/sys_select.in.h298
-rw-r--r--lib/sys_time.in.h205
-rw-r--r--lib/timespec-add.c71
-rw-r--r--lib/timespec-sub.c72
-rw-r--r--lib/timespec.h82
-rw-r--r--lib/utimens.c533
-rw-r--r--lib/utimens.h19
12 files changed, 1816 insertions, 0 deletions
diff --git a/lib/dtotimespec.c b/lib/dtotimespec.c
new file mode 100644
index 00000000000..f30fa075077
--- /dev/null
+++ b/lib/dtotimespec.c
@@ -0,0 +1,69 @@
1/* Convert double to timespec.
2
3 Copyright (C) 2011-2012 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 of the License, or
8 (at your option) 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 Paul Eggert */
19
20/* Convert the double value SEC to a struct timespec. Round toward
21 positive infinity. On overflow, return an extremal value. */
22
23#include <config.h>
24
25#include "timespec.h"
26
27#include "intprops.h"
28
29struct timespec
30dtotimespec (double sec)
31{
32 enum { BILLION = 1000 * 1000 * 1000 };
33 double min_representable = TYPE_MINIMUM (time_t);
34 double max_representable =
35 ((TYPE_MAXIMUM (time_t) * (double) BILLION + (BILLION - 1))
36 / BILLION);
37 struct timespec r;
38
39 if (! (min_representable < sec))
40 {
41 r.tv_sec = TYPE_MINIMUM (time_t);
42 r.tv_nsec = 0;
43 }
44 else if (! (sec < max_representable))
45 {
46 r.tv_sec = TYPE_MAXIMUM (time_t);
47 r.tv_nsec = BILLION - 1;
48 }
49 else
50 {
51 time_t s = sec;
52 double frac = BILLION * (sec - s);
53 long ns = frac;
54 ns += ns < frac;
55 s += ns / BILLION;
56 ns %= BILLION;
57
58 if (ns < 0)
59 {
60 s--;
61 ns += BILLION;
62 }
63
64 r.tv_sec = s;
65 r.tv_nsec = ns;
66 }
67
68 return r;
69}
diff --git a/lib/gettime.c b/lib/gettime.c
new file mode 100644
index 00000000000..8075bfaf999
--- /dev/null
+++ b/lib/gettime.c
@@ -0,0 +1,48 @@
1/* gettime -- get the system clock
2
3 Copyright (C) 2002, 2004-2007, 2009-2012 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 of the License, or
8 (at your option) 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 Paul Eggert. */
19
20#include <config.h>
21
22#include "timespec.h"
23
24#include <sys/time.h>
25
26/* Get the system time into *TS. */
27
28void
29gettime (struct timespec *ts)
30{
31#if HAVE_NANOTIME
32 nanotime (ts);
33#else
34
35# if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
36 if (clock_gettime (CLOCK_REALTIME, ts) == 0)
37 return;
38# endif
39
40 {
41 struct timeval tv;
42 gettimeofday (&tv, NULL);
43 ts->tv_sec = tv.tv_sec;
44 ts->tv_nsec = tv.tv_usec * 1000;
45 }
46
47#endif
48}
diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c
new file mode 100644
index 00000000000..5d35060950a
--- /dev/null
+++ b/lib/gettimeofday.c
@@ -0,0 +1,154 @@
1/* Provide gettimeofday for systems that don't have it or for which it's broken.
2
3 Copyright (C) 2001-2003, 2005-2007, 2009-2012 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 <sys/time.h>
24
25#include <time.h>
26
27#if HAVE_SYS_TIMEB_H
28# include <sys/timeb.h>
29#endif
30
31#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME
32
33/* Work around the bug in some systems whereby gettimeofday clobbers
34 the static buffer that localtime uses for its return value. The
35 gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has
36 this problem. The tzset replacement is necessary for at least
37 Solaris 2.5, 2.5.1, and 2.6. */
38
39static struct tm tm_zero_buffer;
40static struct tm *localtime_buffer_addr = &tm_zero_buffer;
41
42# undef localtime
43extern struct tm *localtime (time_t const *);
44
45# undef gmtime
46extern struct tm *gmtime (time_t const *);
47
48/* This is a wrapper for localtime. It is used only on systems for which
49 gettimeofday clobbers the static buffer used for localtime's result.
50
51 On the first call, record the address of the static buffer that
52 localtime uses for its result. */
53
54struct tm *
55rpl_localtime (time_t const *timep)
56{
57 struct tm *tm = localtime (timep);
58
59 if (localtime_buffer_addr == &tm_zero_buffer)
60 localtime_buffer_addr = tm;
61
62 return tm;
63}
64
65/* Same as above, since gmtime and localtime use the same buffer. */
66struct tm *
67rpl_gmtime (time_t const *timep)
68{
69 struct tm *tm = gmtime (timep);
70
71 if (localtime_buffer_addr == &tm_zero_buffer)
72 localtime_buffer_addr = tm;
73
74 return tm;
75}
76
77#endif /* GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME */
78
79#if TZSET_CLOBBERS_LOCALTIME
80
81# undef tzset
82extern void tzset (void);
83
84/* This is a wrapper for tzset, for systems on which tzset may clobber
85 the static buffer used for localtime's result. */
86void
87rpl_tzset (void)
88{
89 /* Save and restore the contents of the buffer used for localtime's
90 result around the call to tzset. */
91 struct tm save = *localtime_buffer_addr;
92 tzset ();
93 *localtime_buffer_addr = save;
94}
95#endif
96
97/* This is a wrapper for gettimeofday. It is used only on systems
98 that lack this function, or whose implementation of this function
99 causes problems. */
100
101int
102gettimeofday (struct timeval *restrict tv, void *restrict tz)
103{
104#undef gettimeofday
105#if HAVE_GETTIMEOFDAY
106# if GETTIMEOFDAY_CLOBBERS_LOCALTIME
107 /* Save and restore the contents of the buffer used for localtime's
108 result around the call to gettimeofday. */
109 struct tm save = *localtime_buffer_addr;
110# endif
111
112# if defined timeval /* 'struct timeval' overridden by gnulib? */
113# undef timeval
114 struct timeval otv;
115 int result = gettimeofday (&otv, (struct timezone *) tz);
116 if (result == 0)
117 {
118 tv->tv_sec = otv.tv_sec;
119 tv->tv_usec = otv.tv_usec;
120 }
121# else
122 int result = gettimeofday (tv, (struct timezone *) tz);
123# endif
124
125# if GETTIMEOFDAY_CLOBBERS_LOCALTIME
126 *localtime_buffer_addr = save;
127# endif
128
129 return result;
130
131#else
132
133# if HAVE__FTIME
134
135 struct _timeb timebuf;
136 _ftime (&timebuf);
137 tv->tv_sec = timebuf.time;
138 tv->tv_usec = timebuf.millitm * 1000;
139
140# else
141
142# if !defined OK_TO_USE_1S_CLOCK
143# error "Only 1-second nominal clock resolution found. Is that intended?" \
144 "If so, compile with the -DOK_TO_USE_1S_CLOCK option."
145# endif
146 tv->tv_sec = time (NULL);
147 tv->tv_usec = 0;
148
149# endif
150
151 return 0;
152
153#endif
154}
diff --git a/lib/pselect.c b/lib/pselect.c
new file mode 100644
index 00000000000..d8ebc70f6c6
--- /dev/null
+++ b/lib/pselect.c
@@ -0,0 +1,76 @@
1/* pselect - synchronous I/O multiplexing
2
3 Copyright 2011-2012 Free Software Foundation, Inc.
4
5 This file is part of gnulib.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, see <http://www.gnu.org/licenses/>. */
19
20/* written by Paul Eggert */
21
22#include <config.h>
23
24#include <sys/select.h>
25
26#include <errno.h>
27#include <signal.h>
28
29/* Examine the size-NFDS file descriptor sets in RFDS, WFDS, and XFDS
30 to see whether some of their descriptors are ready for reading,
31 ready for writing, or have exceptions pending. Wait for at most
32 TIMEOUT seconds, and use signal mask SIGMASK while waiting. A null
33 pointer parameter stands for no descriptors, an infinite timeout,
34 or an unaffected signal mask. */
35
36int
37pselect (int nfds, fd_set *restrict rfds,
38 fd_set *restrict wfds, fd_set *restrict xfds,
39 struct timespec const *restrict timeout,
40 sigset_t const *restrict sigmask)
41{
42 int select_result;
43 sigset_t origmask;
44 struct timeval tv, *tvp;
45
46 if (timeout)
47 {
48 if (! (0 <= timeout->tv_nsec && timeout->tv_nsec < 1000000000))
49 {
50 errno = EINVAL;
51 return -1;
52 }
53
54 tv.tv_sec = timeout->tv_sec;
55 tv.tv_usec = (timeout->tv_nsec + 999) / 1000;
56 tvp = &tv;
57 }
58 else
59 tvp = NULL;
60
61 /* Signal mask munging should be atomic, but this is the best we can
62 do in this emulation. */
63 if (sigmask)
64 pthread_sigmask (SIG_SETMASK, sigmask, &origmask);
65
66 select_result = select (nfds, rfds, wfds, xfds, tvp);
67
68 if (sigmask)
69 {
70 int select_errno = errno;
71 pthread_sigmask (SIG_SETMASK, &origmask, NULL);
72 errno = select_errno;
73 }
74
75 return select_result;
76}
diff --git a/lib/stat-time.h b/lib/stat-time.h
new file mode 100644
index 00000000000..30c2acdab63
--- /dev/null
+++ b/lib/stat-time.h
@@ -0,0 +1,189 @@
1/* stat-related time functions.
2
3 Copyright (C) 2005, 2007, 2009-2012 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 of the License, or
8 (at your option) 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 Paul Eggert. */
19
20#ifndef STAT_TIME_H
21#define STAT_TIME_H 1
22
23#include <sys/stat.h>
24#include <time.h>
25
26/* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type
27 struct timespec, if available. If not, then STAT_TIMESPEC_NS (ST,
28 ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST,
29 if available. ST_XTIM can be st_atim, st_ctim, st_mtim, or st_birthtim
30 for access, status change, data modification, or birth (creation)
31 time respectively.
32
33 These macros are private to stat-time.h. */
34#if defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
35# ifdef TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
36# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
37# else
38# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
39# endif
40#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
41# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
42#elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
43# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
44#elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
45# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
46#endif
47
48/* Return the nanosecond component of *ST's access time. */
49static inline long int
50get_stat_atime_ns (struct stat const *st)
51{
52# if defined STAT_TIMESPEC
53 return STAT_TIMESPEC (st, st_atim).tv_nsec;
54# elif defined STAT_TIMESPEC_NS
55 return STAT_TIMESPEC_NS (st, st_atim);
56# else
57 return 0;
58# endif
59}
60
61/* Return the nanosecond component of *ST's status change time. */
62static inline long int
63get_stat_ctime_ns (struct stat const *st)
64{
65# if defined STAT_TIMESPEC
66 return STAT_TIMESPEC (st, st_ctim).tv_nsec;
67# elif defined STAT_TIMESPEC_NS
68 return STAT_TIMESPEC_NS (st, st_ctim);
69# else
70 return 0;
71# endif
72}
73
74/* Return the nanosecond component of *ST's data modification time. */
75static inline long int
76get_stat_mtime_ns (struct stat const *st)
77{
78# if defined STAT_TIMESPEC
79 return STAT_TIMESPEC (st, st_mtim).tv_nsec;
80# elif defined STAT_TIMESPEC_NS
81 return STAT_TIMESPEC_NS (st, st_mtim);
82# else
83 return 0;
84# endif
85}
86
87/* Return the nanosecond component of *ST's birth time. */
88static inline long int
89get_stat_birthtime_ns (struct stat const *st)
90{
91# if defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
92 return STAT_TIMESPEC (st, st_birthtim).tv_nsec;
93# elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
94 return STAT_TIMESPEC_NS (st, st_birthtim);
95# else
96 /* Avoid a "parameter unused" warning. */
97 (void) st;
98 return 0;
99# endif
100}
101
102/* Return *ST's access time. */
103static inline struct timespec
104get_stat_atime (struct stat const *st)
105{
106#ifdef STAT_TIMESPEC
107 return STAT_TIMESPEC (st, st_atim);
108#else
109 struct timespec t;
110 t.tv_sec = st->st_atime;
111 t.tv_nsec = get_stat_atime_ns (st);
112 return t;
113#endif
114}
115
116/* Return *ST's status change time. */
117static inline struct timespec
118get_stat_ctime (struct stat const *st)
119{
120#ifdef STAT_TIMESPEC
121 return STAT_TIMESPEC (st, st_ctim);
122#else
123 struct timespec t;
124 t.tv_sec = st->st_ctime;
125 t.tv_nsec = get_stat_ctime_ns (st);
126 return t;
127#endif
128}
129
130/* Return *ST's data modification time. */
131static inline struct timespec
132get_stat_mtime (struct stat const *st)
133{
134#ifdef STAT_TIMESPEC
135 return STAT_TIMESPEC (st, st_mtim);
136#else
137 struct timespec t;
138 t.tv_sec = st->st_mtime;
139 t.tv_nsec = get_stat_mtime_ns (st);
140 return t;
141#endif
142}
143
144/* Return *ST's birth time, if available; otherwise return a value
145 with tv_sec and tv_nsec both equal to -1. */
146static inline struct timespec
147get_stat_birthtime (struct stat const *st)
148{
149 struct timespec t;
150
151#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
152 || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC)
153 t = STAT_TIMESPEC (st, st_birthtim);
154#elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
155 t.tv_sec = st->st_birthtime;
156 t.tv_nsec = st->st_birthtimensec;
157#elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
158 /* Native Windows platforms (but not Cygwin) put the "file creation
159 time" in st_ctime (!). See
160 <http://msdn2.microsoft.com/de-de/library/14h5k7ff(VS.80).aspx>. */
161 t.tv_sec = st->st_ctime;
162 t.tv_nsec = 0;
163#else
164 /* Birth time is not supported. */
165 t.tv_sec = -1;
166 t.tv_nsec = -1;
167 /* Avoid a "parameter unused" warning. */
168 (void) st;
169#endif
170
171#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
172 || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC \
173 || defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
174 /* FreeBSD and NetBSD sometimes signal the absence of knowledge by
175 using zero. Attempt to work around this problem. Alas, this can
176 report failure even for valid time stamps. Also, NetBSD
177 sometimes returns junk in the birth time fields; work around this
178 bug if it is detected. */
179 if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000))
180 {
181 t.tv_sec = -1;
182 t.tv_nsec = -1;
183 }
184#endif
185
186 return t;
187}
188
189#endif
diff --git a/lib/sys_select.in.h b/lib/sys_select.in.h
new file mode 100644
index 00000000000..0aee2a16cbf
--- /dev/null
+++ b/lib/sys_select.in.h
@@ -0,0 +1,298 @@
1/* Substitute for <sys/select.h>.
2 Copyright (C) 2007-2012 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>. */
16
17# if __GNUC__ >= 3
18@PRAGMA_SYSTEM_HEADER@
19# endif
20@PRAGMA_COLUMNS@
21
22/* On OSF/1, <sys/types.h> and <sys/time.h> include <sys/select.h>.
23 Simply delegate to the system's header in this case. */
24#if @HAVE_SYS_SELECT_H@ && defined __osf__ && (defined _SYS_TYPES_H_ && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H) && defined _OSF_SOURCE
25
26# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H
27# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
28
29#elif @HAVE_SYS_SELECT_H@ && defined __osf__ && (defined _SYS_TIME_H_ && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H) && defined _OSF_SOURCE
30
31# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H
32# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
33
34/* On IRIX 6.5, <sys/timespec.h> includes <sys/types.h>, which includes
35 <sys/bsd_types.h>, which includes <sys/select.h>. At this point we cannot
36 include <signal.h>, because that includes <internal/signal_core.h>, which
37 gives a syntax error because <sys/timespec.h> has not been completely
38 processed. Simply delegate to the system's header in this case. */
39#elif @HAVE_SYS_SELECT_H@ && defined __sgi && (defined _SYS_BSD_TYPES_H && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H)
40
41# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H
42# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
43
44/* On OpenBSD 5.0, <pthread.h> includes <sys/types.h>, which includes
45 <sys/select.h>. At this point we cannot include <signal.h>, because that
46 includes gnulib's pthread.h override, which gives a syntax error because
47 /usr/include/pthread.h has not been completely processed. Simply delegate
48 to the system's header in this case. */
49#elif @HAVE_SYS_SELECT_H@ && defined __OpenBSD__ && (defined _PTHREAD_H_ && !defined PTHREAD_MUTEX_INITIALIZER)
50
51# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
52
53#else
54
55#ifndef _@GUARD_PREFIX@_SYS_SELECT_H
56
57/* On many platforms, <sys/select.h> assumes prior inclusion of
58 <sys/types.h>. Also, mingw defines sigset_t there, instead of
59 in <signal.h> where it belongs. */
60#include <sys/types.h>
61
62#if @HAVE_SYS_SELECT_H@
63
64/* On OSF/1 4.0, <sys/select.h> provides only a forward declaration
65 of 'struct timeval', and no definition of this type.
66 Also, Mac OS X, AIX, HP-UX, IRIX, Solaris, Interix declare select()
67 in <sys/time.h>.
68 But avoid namespace pollution on glibc systems. */
69# ifndef __GLIBC__
70# include <sys/time.h>
71# endif
72
73/* On AIX 7 and Solaris 10, <sys/select.h> provides an FD_ZERO implementation
74 that relies on memset(), but without including <string.h>.
75 But in any case avoid namespace pollution on glibc systems. */
76# if (defined __OpenBSD__ || defined _AIX || defined __sun || defined __osf__ || defined __BEOS__) \
77 && ! defined __GLIBC__
78# include <string.h>
79# endif
80
81/* The include_next requires a split double-inclusion guard. */
82# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
83
84#endif
85
86/* Get definition of 'sigset_t'.
87 But avoid namespace pollution on glibc systems.
88 Do this after the include_next (for the sake of OpenBSD 5.0) but before
89 the split double-inclusion guard (for the sake of Solaris). */
90#if !(defined __GLIBC__ && !defined __UCLIBC__)
91# include <signal.h>
92#endif
93
94#ifndef _@GUARD_PREFIX@_SYS_SELECT_H
95#define _@GUARD_PREFIX@_SYS_SELECT_H
96
97#if !@HAVE_SYS_SELECT_H@
98/* A platform that lacks <sys/select.h>. */
99/* Get the 'struct timeval' and 'fd_set' types and the FD_* macros
100 on most platforms. */
101# include <sys/time.h>
102/* On HP-UX 11, <sys/time.h> provides an FD_ZERO implementation
103 that relies on memset(), but without including <string.h>. */
104# if defined __hpux
105# include <string.h>
106# endif
107/* On native Windows platforms:
108 Get the 'fd_set' type.
109 Get the close() declaration before we override it. */
110# if @HAVE_WINSOCK2_H@
111# if !defined _GL_INCLUDING_WINSOCK2_H
112# define _GL_INCLUDING_WINSOCK2_H
113# include <winsock2.h>
114# undef _GL_INCLUDING_WINSOCK2_H
115# endif
116# include <io.h>
117# endif
118#endif
119
120/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
121
122/* The definition of _GL_WARN_ON_USE is copied here. */
123
124
125/* Fix some definitions from <winsock2.h>. */
126
127#if @HAVE_WINSOCK2_H@
128
129# if !GNULIB_defined_rpl_fd_isset
130
131/* Re-define FD_ISSET to avoid a WSA call while we are not using
132 network sockets. */
133static inline int
134rpl_fd_isset (SOCKET fd, fd_set * set)
135{
136 u_int i;
137 if (set == NULL)
138 return 0;
139
140 for (i = 0; i < set->fd_count; i++)
141 if (set->fd_array[i] == fd)
142 return 1;
143
144 return 0;
145}
146
147# define GNULIB_defined_rpl_fd_isset 1
148# endif
149
150# undef FD_ISSET
151# define FD_ISSET(fd, set) rpl_fd_isset(fd, set)
152
153#endif
154
155/* Hide some function declarations from <winsock2.h>. */
156
157#if @HAVE_WINSOCK2_H@
158# if !defined _@GUARD_PREFIX@_UNISTD_H
159# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
160# undef close
161# define close close_used_without_including_unistd_h
162# else
163 _GL_WARN_ON_USE (close,
164 "close() used without including <unistd.h>");
165# endif
166# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
167# undef gethostname
168# define gethostname gethostname_used_without_including_unistd_h
169# else
170 _GL_WARN_ON_USE (gethostname,
171 "gethostname() used without including <unistd.h>");
172# endif
173# endif
174# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H
175# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
176# undef socket
177# define socket socket_used_without_including_sys_socket_h
178# undef connect
179# define connect connect_used_without_including_sys_socket_h
180# undef accept
181# define accept accept_used_without_including_sys_socket_h
182# undef bind
183# define bind bind_used_without_including_sys_socket_h
184# undef getpeername
185# define getpeername getpeername_used_without_including_sys_socket_h
186# undef getsockname
187# define getsockname getsockname_used_without_including_sys_socket_h
188# undef getsockopt
189# define getsockopt getsockopt_used_without_including_sys_socket_h
190# undef listen
191# define listen listen_used_without_including_sys_socket_h
192# undef recv
193# define recv recv_used_without_including_sys_socket_h
194# undef send
195# define send send_used_without_including_sys_socket_h
196# undef recvfrom
197# define recvfrom recvfrom_used_without_including_sys_socket_h
198# undef sendto
199# define sendto sendto_used_without_including_sys_socket_h
200# undef setsockopt
201# define setsockopt setsockopt_used_without_including_sys_socket_h
202# undef shutdown
203# define shutdown shutdown_used_without_including_sys_socket_h
204# else
205 _GL_WARN_ON_USE (socket,
206 "socket() used without including <sys/socket.h>");
207 _GL_WARN_ON_USE (connect,
208 "connect() used without including <sys/socket.h>");
209 _GL_WARN_ON_USE (accept,
210 "accept() used without including <sys/socket.h>");
211 _GL_WARN_ON_USE (bind,
212 "bind() used without including <sys/socket.h>");
213 _GL_WARN_ON_USE (getpeername,
214 "getpeername() used without including <sys/socket.h>");
215 _GL_WARN_ON_USE (getsockname,
216 "getsockname() used without including <sys/socket.h>");
217 _GL_WARN_ON_USE (getsockopt,
218 "getsockopt() used without including <sys/socket.h>");
219 _GL_WARN_ON_USE (listen,
220 "listen() used without including <sys/socket.h>");
221 _GL_WARN_ON_USE (recv,
222 "recv() used without including <sys/socket.h>");
223 _GL_WARN_ON_USE (send,
224 "send() used without including <sys/socket.h>");
225 _GL_WARN_ON_USE (recvfrom,
226 "recvfrom() used without including <sys/socket.h>");
227 _GL_WARN_ON_USE (sendto,
228 "sendto() used without including <sys/socket.h>");
229 _GL_WARN_ON_USE (setsockopt,
230 "setsockopt() used without including <sys/socket.h>");
231 _GL_WARN_ON_USE (shutdown,
232 "shutdown() used without including <sys/socket.h>");
233# endif
234# endif
235#endif
236
237
238#if @GNULIB_PSELECT@
239# if @REPLACE_PSELECT@
240# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
241# undef pselect
242# define pselect rpl_pselect
243# endif
244_GL_FUNCDECL_RPL (pselect, int,
245 (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
246 struct timespec const *restrict, const sigset_t *restrict));
247_GL_CXXALIAS_RPL (pselect, int,
248 (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
249 struct timespec const *restrict, const sigset_t *restrict));
250# else
251# if !@HAVE_PSELECT@
252_GL_FUNCDECL_SYS (pselect, int,
253 (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
254 struct timespec const *restrict, const sigset_t *restrict));
255# endif
256_GL_CXXALIAS_SYS (pselect, int,
257 (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
258 struct timespec const *restrict, const sigset_t *restrict));
259# endif
260_GL_CXXALIASWARN (pselect);
261#elif defined GNULIB_POSIXCHECK
262# undef pselect
263# if HAVE_RAW_DECL_PSELECT
264_GL_WARN_ON_USE (pselect, "pselect is not portable - "
265 "use gnulib module pselect for portability");
266# endif
267#endif
268
269#if @GNULIB_SELECT@
270# if @REPLACE_SELECT@
271# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
272# undef select
273# define select rpl_select
274# endif
275_GL_FUNCDECL_RPL (select, int,
276 (int, fd_set *, fd_set *, fd_set *, struct timeval *));
277_GL_CXXALIAS_RPL (select, int,
278 (int, fd_set *, fd_set *, fd_set *, struct timeval *));
279# else
280_GL_CXXALIAS_SYS (select, int,
281 (int, fd_set *, fd_set *, fd_set *, struct timeval *));
282# endif
283_GL_CXXALIASWARN (select);
284#elif @HAVE_WINSOCK2_H@
285# undef select
286# define select select_used_without_requesting_gnulib_module_select
287#elif defined GNULIB_POSIXCHECK
288# undef select
289# if HAVE_RAW_DECL_SELECT
290_GL_WARN_ON_USE (select, "select is not always POSIX compliant - "
291 "use gnulib module select for portability");
292# endif
293#endif
294
295
296#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */
297#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */
298#endif /* OSF/1 */
diff --git a/lib/sys_time.in.h b/lib/sys_time.in.h
new file mode 100644
index 00000000000..d915cee467a
--- /dev/null
+++ b/lib/sys_time.in.h
@@ -0,0 +1,205 @@
1/* Provide a more complete sys/time.h.
2
3 Copyright (C) 2007-2012 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 Paul Eggert. */
19
20#if __GNUC__ >= 3
21@PRAGMA_SYSTEM_HEADER@
22#endif
23@PRAGMA_COLUMNS@
24
25#if defined _@GUARD_PREFIX@_SYS_TIME_H
26
27/* Simply delegate to the system's header, without adding anything. */
28# if @HAVE_SYS_TIME_H@
29# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@
30# endif
31
32#else
33
34# define _@GUARD_PREFIX@_SYS_TIME_H
35
36# if @HAVE_SYS_TIME_H@
37# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@
38# else
39# include <time.h>
40# endif
41
42/* On native Windows with MSVC, get the 'struct timeval' type.
43 Also, on native Windows with a 64-bit time_t, where we are overriding the
44 'struct timeval' type, get all declarations of system functions whose
45 signature contains 'struct timeval'. */
46# if (defined _MSC_VER || @REPLACE_STRUCT_TIMEVAL@) && @HAVE_WINSOCK2_H@ && !defined _GL_INCLUDING_WINSOCK2_H
47# define _GL_INCLUDING_WINSOCK2_H
48# include <winsock2.h>
49# undef _GL_INCLUDING_WINSOCK2_H
50# endif
51
52/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
53
54/* The definition of _GL_ARG_NONNULL is copied here. */
55
56/* The definition of _GL_WARN_ON_USE is copied here. */
57
58# ifdef __cplusplus
59extern "C" {
60# endif
61
62# if !@HAVE_STRUCT_TIMEVAL@ || @REPLACE_STRUCT_TIMEVAL@
63
64# if @REPLACE_STRUCT_TIMEVAL@
65# define timeval rpl_timeval
66# endif
67
68# if !GNULIB_defined_struct_timeval
69struct timeval
70{
71 time_t tv_sec;
72 long int tv_usec;
73};
74# define GNULIB_defined_struct_timeval 1
75# endif
76
77# endif
78
79# ifdef __cplusplus
80}
81# endif
82
83# if @GNULIB_GETTIMEOFDAY@
84# if @REPLACE_GETTIMEOFDAY@
85# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
86# undef gettimeofday
87# define gettimeofday rpl_gettimeofday
88# endif
89_GL_FUNCDECL_RPL (gettimeofday, int,
90 (struct timeval *restrict, void *restrict)
91 _GL_ARG_NONNULL ((1)));
92_GL_CXXALIAS_RPL (gettimeofday, int,
93 (struct timeval *restrict, void *restrict));
94# else
95# if !@HAVE_GETTIMEOFDAY@
96_GL_FUNCDECL_SYS (gettimeofday, int,
97 (struct timeval *restrict, void *restrict)
98 _GL_ARG_NONNULL ((1)));
99# endif
100/* Need to cast, because on glibc systems, by default, the second argument is
101 struct timezone *. */
102_GL_CXXALIAS_SYS_CAST (gettimeofday, int,
103 (struct timeval *restrict, void *restrict));
104# endif
105_GL_CXXALIASWARN (gettimeofday);
106# elif defined GNULIB_POSIXCHECK
107# undef gettimeofday
108# if HAVE_RAW_DECL_GETTIMEOFDAY
109_GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - "
110 "use gnulib module gettimeofday for portability");
111# endif
112# endif
113
114/* Hide some function declarations from <winsock2.h>. */
115
116# if defined _MSC_VER && @HAVE_WINSOCK2_H@
117# if !defined _@GUARD_PREFIX@_UNISTD_H
118# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
119# undef close
120# define close close_used_without_including_unistd_h
121# else
122 _GL_WARN_ON_USE (close,
123 "close() used without including <unistd.h>");
124# endif
125# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
126# undef gethostname
127# define gethostname gethostname_used_without_including_unistd_h
128# else
129 _GL_WARN_ON_USE (gethostname,
130 "gethostname() used without including <unistd.h>");
131# endif
132# endif
133# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H
134# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
135# undef socket
136# define socket socket_used_without_including_sys_socket_h
137# undef connect
138# define connect connect_used_without_including_sys_socket_h
139# undef accept
140# define accept accept_used_without_including_sys_socket_h
141# undef bind
142# define bind bind_used_without_including_sys_socket_h
143# undef getpeername
144# define getpeername getpeername_used_without_including_sys_socket_h
145# undef getsockname
146# define getsockname getsockname_used_without_including_sys_socket_h
147# undef getsockopt
148# define getsockopt getsockopt_used_without_including_sys_socket_h
149# undef listen
150# define listen listen_used_without_including_sys_socket_h
151# undef recv
152# define recv recv_used_without_including_sys_socket_h
153# undef send
154# define send send_used_without_including_sys_socket_h
155# undef recvfrom
156# define recvfrom recvfrom_used_without_including_sys_socket_h
157# undef sendto
158# define sendto sendto_used_without_including_sys_socket_h
159# undef setsockopt
160# define setsockopt setsockopt_used_without_including_sys_socket_h
161# undef shutdown
162# define shutdown shutdown_used_without_including_sys_socket_h
163# else
164 _GL_WARN_ON_USE (socket,
165 "socket() used without including <sys/socket.h>");
166 _GL_WARN_ON_USE (connect,
167 "connect() used without including <sys/socket.h>");
168 _GL_WARN_ON_USE (accept,
169 "accept() used without including <sys/socket.h>");
170 _GL_WARN_ON_USE (bind,
171 "bind() used without including <sys/socket.h>");
172 _GL_WARN_ON_USE (getpeername,
173 "getpeername() used without including <sys/socket.h>");
174 _GL_WARN_ON_USE (getsockname,
175 "getsockname() used without including <sys/socket.h>");
176 _GL_WARN_ON_USE (getsockopt,
177 "getsockopt() used without including <sys/socket.h>");
178 _GL_WARN_ON_USE (listen,
179 "listen() used without including <sys/socket.h>");
180 _GL_WARN_ON_USE (recv,
181 "recv() used without including <sys/socket.h>");
182 _GL_WARN_ON_USE (send,
183 "send() used without including <sys/socket.h>");
184 _GL_WARN_ON_USE (recvfrom,
185 "recvfrom() used without including <sys/socket.h>");
186 _GL_WARN_ON_USE (sendto,
187 "sendto() used without including <sys/socket.h>");
188 _GL_WARN_ON_USE (setsockopt,
189 "setsockopt() used without including <sys/socket.h>");
190 _GL_WARN_ON_USE (shutdown,
191 "shutdown() used without including <sys/socket.h>");
192# endif
193# endif
194# if !defined _@GUARD_PREFIX@_SYS_SELECT_H
195# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
196# undef select
197# define select select_used_without_including_sys_select_h
198# else
199 _GL_WARN_ON_USE (select,
200 "select() used without including <sys/select.h>");
201# endif
202# endif
203# endif
204
205#endif /* _@GUARD_PREFIX@_SYS_TIME_H */
diff --git a/lib/timespec-add.c b/lib/timespec-add.c
new file mode 100644
index 00000000000..4e5c641ac12
--- /dev/null
+++ b/lib/timespec-add.c
@@ -0,0 +1,71 @@
1/* Add two struct timespec values.
2
3 Copyright (C) 2011-2012 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 of the License, or
8 (at your option) 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 Paul Eggert. */
19
20/* Return the sum of two timespec values A and B. On overflow, return
21 an extremal value. This assumes 0 <= tv_nsec <= 999999999. */
22
23#include <config.h>
24#include "timespec.h"
25
26#include "intprops.h"
27
28struct timespec
29timespec_add (struct timespec a, struct timespec b)
30{
31 struct timespec r;
32 time_t rs = a.tv_sec;
33 time_t bs = b.tv_sec;
34 int ns = a.tv_nsec + b.tv_nsec;
35 int nsd = ns - 1000000000;
36 int rns = ns;
37
38 if (0 <= nsd)
39 {
40 rns = nsd;
41 if (rs == TYPE_MAXIMUM (time_t))
42 {
43 if (0 <= bs)
44 goto high_overflow;
45 bs++;
46 }
47 else
48 rs++;
49 }
50
51 if (INT_ADD_OVERFLOW (rs, bs))
52 {
53 if (rs < 0)
54 {
55 rs = TYPE_MINIMUM (time_t);
56 rns = 0;
57 }
58 else
59 {
60 high_overflow:
61 rs = TYPE_MAXIMUM (time_t);
62 rns = 999999999;
63 }
64 }
65 else
66 rs += bs;
67
68 r.tv_sec = rs;
69 r.tv_nsec = rns;
70 return r;
71}
diff --git a/lib/timespec-sub.c b/lib/timespec-sub.c
new file mode 100644
index 00000000000..0b3bb1b57e1
--- /dev/null
+++ b/lib/timespec-sub.c
@@ -0,0 +1,72 @@
1/* Subtract two struct timespec values.
2
3 Copyright (C) 2011-2012 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 of the License, or
8 (at your option) 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 Paul Eggert. */
19
20/* Return the difference between two timespec values A and B. On
21 overflow, return an extremal value. This assumes 0 <= tv_nsec <=
22 999999999. */
23
24#include <config.h>
25#include <config.h>
26#include "timespec.h"
27
28#include "intprops.h"
29
30struct timespec
31timespec_sub (struct timespec a, struct timespec b)
32{
33 struct timespec r;
34 time_t rs = a.tv_sec;
35 time_t bs = b.tv_sec;
36 int ns = a.tv_nsec - b.tv_nsec;
37 int rns = ns;
38
39 if (ns < 0)
40 {
41 rns = ns + 1000000000;
42 if (rs == TYPE_MINIMUM (time_t))
43 {
44 if (bs <= 0)
45 goto low_overflow;
46 bs--;
47 }
48 else
49 rs--;
50 }
51
52 if (INT_SUBTRACT_OVERFLOW (rs, bs))
53 {
54 if (rs < 0)
55 {
56 low_overflow:
57 rs = TYPE_MINIMUM (time_t);
58 rns = 0;
59 }
60 else
61 {
62 rs = TYPE_MAXIMUM (time_t);
63 rns = 999999999;
64 }
65 }
66 else
67 rs -= bs;
68
69 r.tv_sec = rs;
70 r.tv_nsec = rns;
71 return r;
72}
diff --git a/lib/timespec.h b/lib/timespec.h
new file mode 100644
index 00000000000..388ddb83a76
--- /dev/null
+++ b/lib/timespec.h
@@ -0,0 +1,82 @@
1/* timespec -- System time interface
2
3 Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2012 Free Software
4 Foundation, Inc.
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19#if ! defined TIMESPEC_H
20# define TIMESPEC_H
21
22# include <time.h>
23
24/* Return negative, zero, positive if A < B, A == B, A > B, respectively.
25
26 For each time stamp T, this code assumes that either:
27
28 * T.tv_nsec is in the range 0..999999999; or
29 * T.tv_sec corresponds to a valid leap second on a host that supports
30 leap seconds, and T.tv_nsec is in the range 1000000000..1999999999; or
31 * T.tv_sec is the minimum time_t value and T.tv_nsec is -1; or
32 T.tv_sec is the maximum time_t value and T.tv_nsec is 2000000000.
33 This allows for special struct timespec values that are less or
34 greater than all possible valid time stamps.
35
36 In all these cases, it is safe to subtract two tv_nsec values and
37 convert the result to integer without worrying about overflow on
38 any platform of interest to the GNU project, since all such
39 platforms have 32-bit int or wider.
40
41 Replacing "(int) (a.tv_nsec - b.tv_nsec)" with something like
42 "a.tv_nsec < b.tv_nsec ? -1 : a.tv_nsec > b.tv_nsec" would cause
43 this function to work in some cases where the above assumption is
44 violated, but not in all cases (e.g., a.tv_sec==1, a.tv_nsec==-2,
45 b.tv_sec==0, b.tv_nsec==999999999) and is arguably not worth the
46 extra instructions. Using a subtraction has the advantage of
47 detecting some invalid cases on platforms that detect integer
48 overflow.
49
50 The (int) cast avoids a gcc -Wconversion warning. */
51
52static inline int
53timespec_cmp (struct timespec a, struct timespec b)
54{
55 return (a.tv_sec < b.tv_sec ? -1
56 : a.tv_sec > b.tv_sec ? 1
57 : (int) (a.tv_nsec - b.tv_nsec));
58}
59
60/* Return -1, 0, 1, depending on the sign of A. A.tv_nsec must be
61 nonnegative. */
62static inline int
63timespec_sign (struct timespec a)
64{
65 return a.tv_sec < 0 ? -1 : a.tv_sec || a.tv_nsec;
66}
67
68struct timespec timespec_add (struct timespec, struct timespec);
69struct timespec timespec_sub (struct timespec, struct timespec);
70struct timespec dtotimespec (double);
71
72/* Return an approximation to A, of type 'double'. */
73static inline double
74timespectod (struct timespec a)
75{
76 return a.tv_sec + a.tv_nsec / 1e9;
77}
78
79void gettime (struct timespec *);
80int settime (struct timespec const *);
81
82#endif
diff --git a/lib/utimens.c b/lib/utimens.c
new file mode 100644
index 00000000000..c126b9551a6
--- /dev/null
+++ b/lib/utimens.c
@@ -0,0 +1,533 @@
1/* Set file access and modification times.
2
3 Copyright (C) 2003-2012 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 3 of the License, or any
8 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 Paul Eggert. */
19
20/* derived from a function in touch.c */
21
22#include <config.h>
23
24#include "utimens.h"
25
26#include <assert.h>
27#include <errno.h>
28#include <fcntl.h>
29#include <stdbool.h>
30#include <sys/stat.h>
31#include <sys/time.h>
32#include <unistd.h>
33
34#include "stat-time.h"
35#include "timespec.h"
36
37#if HAVE_UTIME_H
38# include <utime.h>
39#endif
40
41/* Some systems (even some that do have <utime.h>) don't declare this
42 structure anywhere. */
43#ifndef HAVE_STRUCT_UTIMBUF
44struct utimbuf
45{
46 long actime;
47 long modtime;
48};
49#endif
50
51/* Avoid recursion with rpl_futimens or rpl_utimensat. */
52#undef futimens
53#undef utimensat
54
55/* Solaris 9 mistakenly succeeds when given a non-directory with a
56 trailing slash. Force the use of rpl_stat for a fix. */
57#ifndef REPLACE_FUNC_STAT_FILE
58# define REPLACE_FUNC_STAT_FILE 0
59#endif
60
61#if HAVE_UTIMENSAT || HAVE_FUTIMENS
62/* Cache variables for whether the utimensat syscall works; used to
63 avoid calling the syscall if we know it will just fail with ENOSYS,
64 and to avoid unnecessary work in massaging timestamps if the
65 syscall will work. Multiple variables are needed, to distinguish
66 between the following scenarios on Linux:
67 utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS
68 kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW
69 kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec
70 kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT
71 utimensat completely works
72 For each cache variable: 0 = unknown, 1 = yes, -1 = no. */
73static int utimensat_works_really;
74static int lutimensat_works_really;
75#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
76
77/* Validate the requested timestamps. Return 0 if the resulting
78 timespec can be used for utimensat (after possibly modifying it to
79 work around bugs in utimensat). Return a positive value if the
80 timespec needs further adjustment based on stat results: 1 if any
81 adjustment is needed for utimes, and 2 if any adjustment is needed
82 for Linux utimensat. Return -1, with errno set to EINVAL, if
83 timespec is out of range. */
84static int
85validate_timespec (struct timespec timespec[2])
86{
87 int result = 0;
88 int utime_omit_count = 0;
89 assert (timespec);
90 if ((timespec[0].tv_nsec != UTIME_NOW
91 && timespec[0].tv_nsec != UTIME_OMIT
92 && (timespec[0].tv_nsec < 0 || 1000000000 <= timespec[0].tv_nsec))
93 || (timespec[1].tv_nsec != UTIME_NOW
94 && timespec[1].tv_nsec != UTIME_OMIT
95 && (timespec[1].tv_nsec < 0 || 1000000000 <= timespec[1].tv_nsec)))
96 {
97 errno = EINVAL;
98 return -1;
99 }
100 /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
101 EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
102 Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
103 fails to bump ctime. */
104 if (timespec[0].tv_nsec == UTIME_NOW
105 || timespec[0].tv_nsec == UTIME_OMIT)
106 {
107 timespec[0].tv_sec = 0;
108 result = 1;
109 if (timespec[0].tv_nsec == UTIME_OMIT)
110 utime_omit_count++;
111 }
112 if (timespec[1].tv_nsec == UTIME_NOW
113 || timespec[1].tv_nsec == UTIME_OMIT)
114 {
115 timespec[1].tv_sec = 0;
116 result = 1;
117 if (timespec[1].tv_nsec == UTIME_OMIT)
118 utime_omit_count++;
119 }
120 return result + (utime_omit_count == 1);
121}
122
123/* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
124 buffer STATBUF to obtain the current timestamps of the file. If
125 both times are UTIME_NOW, set *TS to NULL (as this can avoid some
126 permissions issues). If both times are UTIME_OMIT, return true
127 (nothing further beyond the prior collection of STATBUF is
128 necessary); otherwise return false. */
129static bool
130update_timespec (struct stat const *statbuf, struct timespec *ts[2])
131{
132 struct timespec *timespec = *ts;
133 if (timespec[0].tv_nsec == UTIME_OMIT
134 && timespec[1].tv_nsec == UTIME_OMIT)
135 return true;
136 if (timespec[0].tv_nsec == UTIME_NOW
137 && timespec[1].tv_nsec == UTIME_NOW)
138 {
139 *ts = NULL;
140 return false;
141 }
142
143 if (timespec[0].tv_nsec == UTIME_OMIT)
144 timespec[0] = get_stat_atime (statbuf);
145 else if (timespec[0].tv_nsec == UTIME_NOW)
146 gettime (&timespec[0]);
147
148 if (timespec[1].tv_nsec == UTIME_OMIT)
149 timespec[1] = get_stat_mtime (statbuf);
150 else if (timespec[1].tv_nsec == UTIME_NOW)
151 gettime (&timespec[1]);
152
153 return false;
154}
155
156/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
157 TIMESPEC[0] and TIMESPEC[1], respectively.
158 FD must be either negative -- in which case it is ignored --
159 or a file descriptor that is open on FILE.
160 If FD is nonnegative, then FILE can be NULL, which means
161 use just futimes (or equivalent) instead of utimes (or equivalent),
162 and fail if on an old system without futimes (or equivalent).
163 If TIMESPEC is null, set the time stamps to the current time.
164 Return 0 on success, -1 (setting errno) on failure. */
165
166int
167fdutimens (int fd, char const *file, struct timespec const timespec[2])
168{
169 struct timespec adjusted_timespec[2];
170 struct timespec *ts = timespec ? adjusted_timespec : NULL;
171 int adjustment_needed = 0;
172 struct stat st;
173
174 if (ts)
175 {
176 adjusted_timespec[0] = timespec[0];
177 adjusted_timespec[1] = timespec[1];
178 adjustment_needed = validate_timespec (ts);
179 }
180 if (adjustment_needed < 0)
181 return -1;
182
183 /* Require that at least one of FD or FILE are potentially valid, to avoid
184 a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
185 than failing. */
186 if (fd < 0 && !file)
187 {
188 errno = EBADF;
189 return -1;
190 }
191
192 /* Some Linux-based NFS clients are buggy, and mishandle time stamps
193 of files in NFS file systems in some cases. We have no
194 configure-time test for this, but please see
195 <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
196 some of the problems with Linux 2.6.16. If this affects you,
197 compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
198 help in some cases, albeit at a cost in performance. But you
199 really should upgrade your kernel to a fixed version, since the
200 problem affects many applications. */
201
202#if HAVE_BUGGY_NFS_TIME_STAMPS
203 if (fd < 0)
204 sync ();
205 else
206 fsync (fd);
207#endif
208
209 /* POSIX 2008 added two interfaces to set file timestamps with
210 nanosecond resolution; newer Linux implements both functions via
211 a single syscall. We provide a fallback for ENOSYS (for example,
212 compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
213 running on Linux 2.6.18 kernel). */
214#if HAVE_UTIMENSAT || HAVE_FUTIMENS
215 if (0 <= utimensat_works_really)
216 {
217 int result;
218# if __linux__
219 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
220 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
221 but work if both times are either explicitly specified or
222 UTIME_NOW. Work around it with a preparatory [f]stat prior
223 to calling futimens/utimensat; fortunately, there is not much
224 timing impact due to the extra syscall even on file systems
225 where UTIME_OMIT would have worked. FIXME: Simplify this in
226 2012, when file system bugs are no longer common. */
227 if (adjustment_needed == 2)
228 {
229 if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
230 return -1;
231 if (ts[0].tv_nsec == UTIME_OMIT)
232 ts[0] = get_stat_atime (&st);
233 else if (ts[1].tv_nsec == UTIME_OMIT)
234 ts[1] = get_stat_mtime (&st);
235 /* Note that st is good, in case utimensat gives ENOSYS. */
236 adjustment_needed++;
237 }
238# endif /* __linux__ */
239# if HAVE_UTIMENSAT
240 if (fd < 0)
241 {
242 result = utimensat (AT_FDCWD, file, ts, 0);
243# ifdef __linux__
244 /* Work around a kernel bug:
245 http://bugzilla.redhat.com/442352
246 http://bugzilla.redhat.com/449910
247 It appears that utimensat can mistakenly return 280 rather
248 than -1 upon ENOSYS failure.
249 FIXME: remove in 2010 or whenever the offending kernels
250 are no longer in common use. */
251 if (0 < result)
252 errno = ENOSYS;
253# endif /* __linux__ */
254 if (result == 0 || errno != ENOSYS)
255 {
256 utimensat_works_really = 1;
257 return result;
258 }
259 }
260# endif /* HAVE_UTIMENSAT */
261# if HAVE_FUTIMENS
262 if (0 <= fd)
263 {
264 result = futimens (fd, ts);
265# ifdef __linux__
266 /* Work around the same bug as above. */
267 if (0 < result)
268 errno = ENOSYS;
269# endif /* __linux__ */
270 if (result == 0 || errno != ENOSYS)
271 {
272 utimensat_works_really = 1;
273 return result;
274 }
275 }
276# endif /* HAVE_FUTIMENS */
277 }
278 utimensat_works_really = -1;
279 lutimensat_works_really = -1;
280#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
281
282 /* The platform lacks an interface to set file timestamps with
283 nanosecond resolution, so do the best we can, discarding any
284 fractional part of the timestamp. */
285
286 if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
287 {
288 if (adjustment_needed != 3
289 && (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
290 return -1;
291 if (ts && update_timespec (&st, &ts))
292 return 0;
293 }
294
295 {
296#if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
297 struct timeval timeval[2];
298 struct timeval *t;
299 if (ts)
300 {
301 timeval[0].tv_sec = ts[0].tv_sec;
302 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
303 timeval[1].tv_sec = ts[1].tv_sec;
304 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
305 t = timeval;
306 }
307 else
308 t = NULL;
309
310 if (fd < 0)
311 {
312# if HAVE_FUTIMESAT
313 return futimesat (AT_FDCWD, file, t);
314# endif
315 }
316 else
317 {
318 /* If futimesat or futimes fails here, don't try to speed things
319 up by returning right away. glibc can incorrectly fail with
320 errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
321 in high security mode doesn't allow ordinary users to read
322 /proc/self, so glibc incorrectly fails with errno == EACCES.
323 If errno == EIO, EPERM, or EROFS, it's probably safe to fail
324 right away, but these cases are rare enough that they're not
325 worth optimizing, and who knows what other messed-up systems
326 are out there? So play it safe and fall back on the code
327 below. */
328
329# if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
330# if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
331# undef futimes
332# define futimes(fd, t) futimesat (fd, NULL, t)
333# endif
334 if (futimes (fd, t) == 0)
335 {
336# if __linux__ && __GLIBC__
337 /* Work around a longstanding glibc bug, still present as
338 of 2010-12-27. On older Linux kernels that lack both
339 utimensat and utimes, glibc's futimes rounds instead of
340 truncating when falling back on utime. The same bug
341 occurs in futimesat with a null 2nd arg. */
342 if (t)
343 {
344 bool abig = 500000 <= t[0].tv_usec;
345 bool mbig = 500000 <= t[1].tv_usec;
346 if ((abig | mbig) && fstat (fd, &st) == 0)
347 {
348 /* If these two subtractions overflow, they'll
349 track the overflows inside the buggy glibc. */
350 time_t adiff = st.st_atime - t[0].tv_sec;
351 time_t mdiff = st.st_mtime - t[1].tv_sec;
352
353 struct timeval *tt = NULL;
354 struct timeval truncated_timeval[2];
355 truncated_timeval[0] = t[0];
356 truncated_timeval[1] = t[1];
357 if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0)
358 {
359 tt = truncated_timeval;
360 tt[0].tv_usec = 0;
361 }
362 if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
363 {
364 tt = truncated_timeval;
365 tt[1].tv_usec = 0;
366 }
367 if (tt)
368 futimes (fd, tt);
369 }
370 }
371# endif
372
373 return 0;
374 }
375# endif
376 }
377#endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
378
379 if (!file)
380 {
381#if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
382 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
383 errno = ENOSYS;
384#endif
385 return -1;
386 }
387
388#if HAVE_WORKING_UTIMES
389 return utimes (file, t);
390#else
391 {
392 struct utimbuf utimbuf;
393 struct utimbuf *ut;
394 if (ts)
395 {
396 utimbuf.actime = ts[0].tv_sec;
397 utimbuf.modtime = ts[1].tv_sec;
398 ut = &utimbuf;
399 }
400 else
401 ut = NULL;
402
403 return utime (file, ut);
404 }
405#endif /* !HAVE_WORKING_UTIMES */
406 }
407}
408
409/* Set the access and modification time stamps of FILE to be
410 TIMESPEC[0] and TIMESPEC[1], respectively. */
411int
412utimens (char const *file, struct timespec const timespec[2])
413{
414 return fdutimens (-1, file, timespec);
415}
416
417/* Set the access and modification time stamps of FILE to be
418 TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
419 symlinks. Fail with ENOSYS if the platform does not support
420 changing symlink timestamps, but FILE was a symlink. */
421int
422lutimens (char const *file, struct timespec const timespec[2])
423{
424 struct timespec adjusted_timespec[2];
425 struct timespec *ts = timespec ? adjusted_timespec : NULL;
426 int adjustment_needed = 0;
427 struct stat st;
428
429 if (ts)
430 {
431 adjusted_timespec[0] = timespec[0];
432 adjusted_timespec[1] = timespec[1];
433 adjustment_needed = validate_timespec (ts);
434 }
435 if (adjustment_needed < 0)
436 return -1;
437
438 /* The Linux kernel did not support symlink timestamps until
439 utimensat, in version 2.6.22, so we don't need to mimic
440 fdutimens' worry about buggy NFS clients. But we do have to
441 worry about bogus return values. */
442
443#if HAVE_UTIMENSAT
444 if (0 <= lutimensat_works_really)
445 {
446 int result;
447# if __linux__
448 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
449 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
450 but work if both times are either explicitly specified or
451 UTIME_NOW. Work around it with a preparatory lstat prior to
452 calling utimensat; fortunately, there is not much timing
453 impact due to the extra syscall even on file systems where
454 UTIME_OMIT would have worked. FIXME: Simplify this in 2012,
455 when file system bugs are no longer common. */
456 if (adjustment_needed == 2)
457 {
458 if (lstat (file, &st))
459 return -1;
460 if (ts[0].tv_nsec == UTIME_OMIT)
461 ts[0] = get_stat_atime (&st);
462 else if (ts[1].tv_nsec == UTIME_OMIT)
463 ts[1] = get_stat_mtime (&st);
464 /* Note that st is good, in case utimensat gives ENOSYS. */
465 adjustment_needed++;
466 }
467# endif /* __linux__ */
468 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
469# ifdef __linux__
470 /* Work around a kernel bug:
471 http://bugzilla.redhat.com/442352
472 http://bugzilla.redhat.com/449910
473 It appears that utimensat can mistakenly return 280 rather
474 than -1 upon ENOSYS failure.
475 FIXME: remove in 2010 or whenever the offending kernels
476 are no longer in common use. */
477 if (0 < result)
478 errno = ENOSYS;
479# endif
480 if (result == 0 || errno != ENOSYS)
481 {
482 utimensat_works_really = 1;
483 lutimensat_works_really = 1;
484 return result;
485 }
486 }
487 lutimensat_works_really = -1;
488#endif /* HAVE_UTIMENSAT */
489
490 /* The platform lacks an interface to set file timestamps with
491 nanosecond resolution, so do the best we can, discarding any
492 fractional part of the timestamp. */
493
494 if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
495 {
496 if (adjustment_needed != 3 && lstat (file, &st))
497 return -1;
498 if (ts && update_timespec (&st, &ts))
499 return 0;
500 }
501
502 /* On Linux, lutimes is a thin wrapper around utimensat, so there is
503 no point trying lutimes if utimensat failed with ENOSYS. */
504#if HAVE_LUTIMES && !HAVE_UTIMENSAT
505 {
506 struct timeval timeval[2];
507 struct timeval *t;
508 int result;
509 if (ts)
510 {
511 timeval[0].tv_sec = ts[0].tv_sec;
512 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
513 timeval[1].tv_sec = ts[1].tv_sec;
514 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
515 t = timeval;
516 }
517 else
518 t = NULL;
519
520 result = lutimes (file, t);
521 if (result == 0 || errno != ENOSYS)
522 return result;
523 }
524#endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
525
526 /* Out of luck for symlinks, but we still handle regular files. */
527 if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
528 return -1;
529 if (!S_ISLNK (st.st_mode))
530 return fdutimens (-1, file, ts);
531 errno = ENOSYS;
532 return -1;
533}
diff --git a/lib/utimens.h b/lib/utimens.h
new file mode 100644
index 00000000000..8c47cf93f88
--- /dev/null
+++ b/lib/utimens.h
@@ -0,0 +1,19 @@
1#include <time.h>
2int fdutimens (int, char const *, struct timespec const [2]);
3int utimens (char const *, struct timespec const [2]);
4int lutimens (char const *, struct timespec const [2]);
5
6#if GNULIB_FDUTIMENSAT
7# include <fcntl.h>
8# include <sys/stat.h>
9
10int fdutimensat (int fd, int dir, char const *name, struct timespec const [2],
11 int atflag);
12
13/* Using this function makes application code slightly more readable. */
14static inline int
15lutimensat (int dir, char const *file, struct timespec const times[2])
16{
17 return utimensat (dir, file, times, AT_SYMLINK_NOFOLLOW);
18}
19#endif