summaryrefslogtreecommitdiff
path: root/lib/gettimeofday.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gettimeofday.c')
-rw-r--r--lib/gettimeofday.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c
new file mode 100644
index 0000000..bd5576c
--- /dev/null
+++ b/lib/gettimeofday.c
@@ -0,0 +1,142 @@
+/* Provide gettimeofday for systems that don't have it or for which it's broken.
+
+ Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+/* Specification. */
+#include <sys/time.h>
+
+#include <time.h>
+
+#if HAVE_SYS_TIMEB_H
+# include <sys/timeb.h>
+#endif
+
+#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME
+
+/* Work around the bug in some systems whereby gettimeofday clobbers
+ the static buffer that localtime uses for its return value. The
+ gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has
+ this problem. The tzset replacement is necessary for at least
+ Solaris 2.5, 2.5.1, and 2.6. */
+
+static struct tm tm_zero_buffer;
+static struct tm *localtime_buffer_addr = &tm_zero_buffer;
+
+/* This is a wrapper for localtime. It is used only on systems for which
+ gettimeofday clobbers the static buffer used for localtime's result.
+
+ On the first call, record the address of the static buffer that
+ localtime uses for its result. */
+
+struct tm *
+localtime (time_t const *timep)
+{
+#undef localtime
+ extern struct tm *localtime (time_t const *);
+ struct tm *tm = localtime (timep);
+
+ if (localtime_buffer_addr == &tm_zero_buffer)
+ localtime_buffer_addr = tm;
+
+ return tm;
+}
+
+/* Same as above, since gmtime and localtime use the same buffer. */
+struct tm *
+gmtime (time_t const *timep)
+{
+#undef gmtime
+ extern struct tm *gmtime (time_t const *);
+ struct tm *tm = gmtime (timep);
+
+ if (localtime_buffer_addr == &tm_zero_buffer)
+ localtime_buffer_addr = tm;
+
+ return tm;
+}
+
+#endif /* GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME */
+
+#if TZSET_CLOBBERS_LOCALTIME
+/* This is a wrapper for tzset, for systems on which tzset may clobber
+ the static buffer used for localtime's result. */
+void
+tzset (void)
+{
+#undef tzset
+ extern void tzset (void);
+
+ /* Save and restore the contents of the buffer used for localtime's
+ result around the call to tzset. */
+ struct tm save = *localtime_buffer_addr;
+ tzset ();
+ *localtime_buffer_addr = save;
+}
+#endif
+
+/* This is a wrapper for gettimeofday. It is used only on systems
+ that lack this function, or whose implementation of this function
+ causes problems. */
+
+int
+rpl_gettimeofday (struct timeval *restrict tv, void *restrict tz)
+{
+#undef gettimeofday
+#if HAVE_GETTIMEOFDAY
+# if GETTIMEOFDAY_CLOBBERS_LOCALTIME
+ /* Save and restore the contents of the buffer used for localtime's
+ result around the call to gettimeofday. */
+ struct tm save = *localtime_buffer_addr;
+# endif
+
+ int result = gettimeofday (tv, tz);
+
+# if GETTIMEOFDAY_CLOBBERS_LOCALTIME
+ *localtime_buffer_addr = save;
+# endif
+
+ return result;
+
+#else
+
+# if HAVE__FTIME
+
+ struct _timeb timebuf;
+ _ftime (&timebuf);
+ tv->tv_sec = timebuf.time;
+ tv->tv_usec = timebuf.millitm * 1000;
+
+# else
+
+# if !defined OK_TO_USE_1S_CLOCK
+# error "Only 1-second nominal clock resolution found. Is that intended?" \
+ "If so, compile with the -DOK_TO_USE_1S_CLOCK option."
+# endif
+ tv->tv_sec = time (NULL);
+ tv->tv_usec = 0;
+
+# endif
+
+ return 0;
+
+#endif
+}