Patch from Martin Lambers <marlam@marlam.de>, from 2005-10-08
[gnulib.git] / lib / gettimeofday.c
1 /* Provide gettimeofday for systems that don't have it, or,
2    work around the bug in some systems whereby gettimeofday clobbers the
3    static buffer that localtime uses for it's return value.  The gettimeofday
4    function from Mac OS X 10.0.4, i.e. Darwin 1.3.7 has this problem.
5    The tzset replacement is necessary for at least Solaris 2.5, 2.5.1, and 2.6.
6
7    Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2, or (at your option)
12    any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software Foundation,
21    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
22
23 /* written by Jim Meyering */
24
25 #include <config.h>
26
27 /* Disable the definitions of these functions (from config.h)
28    so we can use the library versions here.  */
29 #undef gettimeofday
30 #undef gmtime
31 #undef localtime
32 #undef tzset
33
34 #include <sys/types.h>
35
36 #if TIME_WITH_SYS_TIME
37 # include <sys/time.h>
38 # include <time.h>
39 #else
40 # if HAVE_SYS_TIME_H
41 #  include <sys/time.h>
42 # else
43 #  include <time.h>
44 # endif
45 #endif
46
47 #include <stdlib.h>
48
49 #if HAVE_SYS_TIMEB_H
50 #include <sys/timeb.h>
51 #endif
52
53 #if GETTIMEOFDAY_CLOBBERS_LOCALTIME
54 static struct tm *localtime_buffer_addr;
55 #endif
56
57 /* This is a wrapper for localtime.  It is used only on systems for which
58    gettimeofday clobbers the static buffer used for localtime's result.
59
60    On the first call, record the address of the static buffer that
61    localtime uses for its result.  */
62
63 #if GETTIMEOFDAY_CLOBBERS_LOCALTIME
64 struct tm *
65 rpl_localtime (const time_t *timep)
66 {
67   struct tm *tm = localtime (timep);
68
69   if (! localtime_buffer_addr)
70     localtime_buffer_addr = tm;
71
72   return tm;
73 }
74 #endif
75
76 /* Same as above, since gmtime and localtime use the same buffer.  */
77 #if GETTIMEOFDAY_CLOBBERS_LOCALTIME
78 struct tm *
79 rpl_gmtime (const time_t *timep)
80 {
81   struct tm *tm = gmtime (timep);
82
83   if (! localtime_buffer_addr)
84     localtime_buffer_addr = tm;
85
86   return tm;
87 }
88 #endif
89
90 /* This is a wrapper for gettimeofday.  
91    It is used only on systems that lack this function, or for whose 
92    implementation of this function causes problems. */
93
94 int
95 rpl_gettimeofday (struct timeval *restrict tv, void *restrict tz)
96 {
97 #if HAVE_GETTIMEOFDAY
98 # if GETTIMEOFDAY_CLOBBERS_LOCALTIME
99
100   /* Save and restore the contents of the buffer used for localtime's result
101      around the call to gettimeofday. */
102   struct tm save;
103   int result;
104
105   if (! localtime_buffer_addr)
106     {
107       time_t t = 0;
108       localtime_buffer_addr = localtime (&t);
109     }
110
111   save = *localtime_buffer_addr;
112   result = gettimeofday (tv, tz);
113   *localtime_buffer_addr = save;
114
115   return result;
116
117 # endif
118 #else
119 # if HAVE__FTIME
120
121   struct _timeb timebuf;
122   
123   _ftime (&timebuf);
124   tv->tv_sec = timebuf.time;
125   tv->tv_usec = timebuf.millitm * 1000;
126
127   return 0;
128
129 # else
130
131   time_t t = time (NULL);
132   
133   if (t == (time_t) -1)
134     return -1;
135   tv->tv_sec = t;
136   tv->tv_usec = 0;
137
138   return 0;
139
140 # endif
141 #endif
142 }
143
144 /* This is a wrapper for tzset. It is used only on systems for which
145    tzset may clobber the static buffer used for localtime's result.
146    Save and restore the contents of the buffer used for localtime's
147    result around the call to tzset.  */
148 #if GETTIMEOFDAY_CLOBBERS_LOCALTIME
149 void
150 rpl_tzset (void)
151 {
152   struct tm save;
153
154   if (! localtime_buffer_addr)
155     {
156       time_t t = 0;
157       localtime_buffer_addr = localtime (&t);
158     }
159
160   save = *localtime_buffer_addr;
161   tzset ();
162   *localtime_buffer_addr = save;
163 }
164 #endif