From 4298ac9305d89cadf90ebb01f0e85bb74fea2c1e Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Wed, 14 Oct 2015 23:53:52 -0500 Subject: [PATCH] include timegm fallback --- .gitignore | 1 + crypto/Makefile.am | 6 ++++ crypto/compat/timegm.c | 71 +++++++++++++++++++++++++++++++++++++++++ include/compat/limits.h | 5 --- include/compat/time.h | 6 +++- m4/check-libc.m4 | 3 ++ 6 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 crypto/compat/timegm.c diff --git a/.gitignore b/.gitignore index 499205f..03ed14a 100644 --- a/.gitignore +++ b/.gitignore @@ -129,6 +129,7 @@ include/openssl/*.h !/crypto/compat/posix_win.c !/crypto/compat/bsd_asprintf.c !/crypto/compat/inet_pton.c +!/crypto/compat/timegm.c !/crypto/compat/ui_openssl_win.c !/crypto/CMakeLists.txt /crypto diff --git a/crypto/Makefile.am b/crypto/Makefile.am index e1e785d..40d82cd 100644 --- a/crypto/Makefile.am +++ b/crypto/Makefile.am @@ -73,6 +73,12 @@ if !HAVE_INET_PTON libcompat_la_SOURCES += compat/inet_pton.c endif +if !HAVE_TIMEGM +if !HAVE__MKGMTIME +libcompat_la_SOURCES += compat/timegm.c +endif +endif + if !HAVE_REALLOCARRAY libcompat_la_SOURCES += compat/reallocarray.c endif diff --git a/crypto/compat/timegm.c b/crypto/compat/timegm.c new file mode 100644 index 0000000..2007140 --- /dev/null +++ b/crypto/compat/timegm.c @@ -0,0 +1,71 @@ +/* + * timegm shims based on example code from in the glibc timegm manpage. + * + * These should be replaced with lockless versions that do not require + * modifying global state. + */ + +#include +#include +#include +#include + +#ifdef _WIN32 +#include +time_t +timegm(struct tm *tm) +{ + time_t ret; + char *tz, *buf; + static volatile HANDLE mtx = NULL; + + if (!mtx) { + HANDLE p = CreateMutex(NULL, FALSE, NULL); + if (InterlockedCompareExchangePointer( + (void **)&mtx, (void *)p, NULL)) + CloseHandle(p); + } + WaitForSingleObject(mtx, INFINITE); + tz = getenv("TZ"); + if (tz) { + if (asprintf(&buf, "TZ=%s", tz) == -1) + buf = NULL; + } + putenv("TZ=UTC"); + tzset(); + ret = mktime(tm); + if (buf) { + putenv(buf); + free(buf); + } else + putenv("TZ="); + tzset(); + ReleaseMutex(mtx); + return ret; +} +#else +#include +time_t +timegm(struct tm *tm) +{ + time_t ret; + char *tz; + static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock(&mtx); + tz = getenv("TZ"); + if (tz) + tz = strdup(tz); + setenv("TZ", "", 1); + tzset(); + ret = mktime(tm); + if (tz) { + setenv("TZ", tz, 1); + free(tz); + } else + unsetenv("TZ"); + tzset(); + pthread_mutex_unlock(&mtx); + return ret; +} +#endif diff --git a/include/compat/limits.h b/include/compat/limits.h index ca96125..18cabf1 100644 --- a/include/compat/limits.h +++ b/include/compat/limits.h @@ -3,9 +3,6 @@ * limits.h compatibility shim */ -#ifndef LIBCRYPTOCOMPAT_LIMITS_H -#define LIBCRYPTOCOMPAT_LIMITS_H - #ifdef _MSC_VER #if _MSC_VER >= 1900 #include <../ucrt/limits.h> @@ -22,5 +19,3 @@ #define PATH_MAX MAXPATHLEN #endif #endif - -#endif diff --git a/include/compat/time.h b/include/compat/time.h index 3ef3bad..3a87548 100644 --- a/include/compat/time.h +++ b/include/compat/time.h @@ -14,6 +14,10 @@ #include_next #endif -#ifdef _WIN32 +#ifndef HAVE_TIMEGM +#ifdef HAVE__MKGMTIME #define timegm(tm) _mkgmtime(tm) +#else +time_t timegm(struct tm *tm); +#endif #endif diff --git a/m4/check-libc.m4 b/m4/check-libc.m4 index c0df011..3efc686 100644 --- a/m4/check-libc.m4 +++ b/m4/check-libc.m4 @@ -4,6 +4,7 @@ AC_CHECK_HEADERS([err.h readpassphrase.h]) # Check for general libc functions AC_CHECK_FUNCS([asprintf inet_pton memmem readpassphrase reallocarray]) AC_CHECK_FUNCS([strlcat strlcpy strndup strnlen strsep strtonum]) +AC_CHECK_FUNCS([timegm _mkgmtime]) AM_CONDITIONAL([HAVE_ASPRINTF], [test "x$ac_cv_func_asprintf" = xyes]) AM_CONDITIONAL([HAVE_INET_PTON], [test "x$ac_cv_func_inet_pton" = xyes]) AM_CONDITIONAL([HAVE_MEMMEM], [test "x$ac_cv_func_memmem" = xyes]) @@ -15,6 +16,8 @@ AM_CONDITIONAL([HAVE_STRNDUP], [test "x$ac_cv_func_strndup" = xyes]) AM_CONDITIONAL([HAVE_STRNLEN], [test "x$ac_cv_func_strnlen" = xyes]) AM_CONDITIONAL([HAVE_STRSEP], [test "x$ac_cv_func_strsep" = xyes]) AM_CONDITIONAL([HAVE_STRTONUM], [test "x$ac_cv_func_strtonum" = xyes]) +AM_CONDITIONAL([HAVE_TIMEGM], [test "x$ac_cv_func_timegm" = xyes]) +AM_CONDITIONAL([HAVE__MKGMTIME], [test "x$ac_cv_func__mkgmtime" = xyes]) ]) AC_DEFUN([CHECK_SYSCALL_COMPAT], [