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-2014 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} 155