aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/build-data/os/cygwin.txt1
-rw-r--r--src/build-data/os/darwin.txt1
-rw-r--r--src/build-data/os/freebsd.txt1
-rw-r--r--src/build-data/os/linux.txt1
-rw-r--r--src/build-data/os/mingw.txt1
-rw-r--r--src/build-data/os/netbsd.txt1
-rw-r--r--src/build-data/os/openbsd.txt1
-rw-r--r--src/build-data/os/windows.txt1
-rw-r--r--src/lib/utils/calendar.cpp61
9 files changed, 64 insertions, 5 deletions
diff --git a/src/build-data/os/cygwin.txt b/src/build-data/os/cygwin.txt
index eb5835a6f..be67e2607 100644
--- a/src/build-data/os/cygwin.txt
+++ b/src/build-data/os/cygwin.txt
@@ -13,4 +13,5 @@ doc_dir docs
<target_features>
gettimeofday
getsid
+timegm
</target_features>
diff --git a/src/build-data/os/darwin.txt b/src/build-data/os/darwin.txt
index f5f2589fb..3a13b34e4 100644
--- a/src/build-data/os/darwin.txt
+++ b/src/build-data/os/darwin.txt
@@ -15,6 +15,7 @@ gmtime_r
memset_s
readdir
getsid
+timegm
</target_features>
<aliases>
diff --git a/src/build-data/os/freebsd.txt b/src/build-data/os/freebsd.txt
index 346145785..32767cb1f 100644
--- a/src/build-data/os/freebsd.txt
+++ b/src/build-data/os/freebsd.txt
@@ -8,4 +8,5 @@ gmtime_r
dlopen
readdir
getsid
+timegm
</target_features>
diff --git a/src/build-data/os/linux.txt b/src/build-data/os/linux.txt
index cb78c33ff..48c3bf318 100644
--- a/src/build-data/os/linux.txt
+++ b/src/build-data/os/linux.txt
@@ -8,6 +8,7 @@ gmtime_r
dlopen
readdir
getsid
+timegm
</target_features>
<aliases>
diff --git a/src/build-data/os/mingw.txt b/src/build-data/os/mingw.txt
index 4f3e7f08b..cc98b11e6 100644
--- a/src/build-data/os/mingw.txt
+++ b/src/build-data/os/mingw.txt
@@ -23,6 +23,7 @@ mingw32
<target_features>
cryptgenrandom
loadlibrary
+mkgmtime
win32_virtual_lock
win32_get_systemtime
</target_features>
diff --git a/src/build-data/os/netbsd.txt b/src/build-data/os/netbsd.txt
index 346145785..32767cb1f 100644
--- a/src/build-data/os/netbsd.txt
+++ b/src/build-data/os/netbsd.txt
@@ -8,4 +8,5 @@ gmtime_r
dlopen
readdir
getsid
+timegm
</target_features>
diff --git a/src/build-data/os/openbsd.txt b/src/build-data/os/openbsd.txt
index 5df133c8e..510a7accd 100644
--- a/src/build-data/os/openbsd.txt
+++ b/src/build-data/os/openbsd.txt
@@ -7,4 +7,5 @@ posix_mlock
gmtime_r
dlopen
readdir
+timegm
</target_features>
diff --git a/src/build-data/os/windows.txt b/src/build-data/os/windows.txt
index c34f2e7ab..fd74fe817 100644
--- a/src/build-data/os/windows.txt
+++ b/src/build-data/os/windows.txt
@@ -15,6 +15,7 @@ install_cmd_exec "copy"
cryptgenrandom
gmtime_s
loadlibrary
+mkgmtime
query_perf_counter
virtual_lock
rtlsecurezeromemory
diff --git a/src/lib/utils/calendar.cpp b/src/lib/utils/calendar.cpp
index f62303e49..966c97730 100644
--- a/src/lib/utils/calendar.cpp
+++ b/src/lib/utils/calendar.cpp
@@ -11,6 +11,7 @@
#include <ctime>
#include <sstream>
#include <iomanip>
+#include <mutex>
namespace Botan {
@@ -34,11 +35,53 @@ std::tm do_gmtime(std::time_t time_val)
return tm;
}
+#if !defined(BOTAN_TARGET_OS_HAS_TIMEGM) && !defined(BOTAN_TARGET_OS_HAS_MKGMTIME)
+
+#pragma message "Caution! A fallback version of timegm() is used which is not thread-safe"
+
+std::mutex ENV_TZ;
+
+std::time_t fallback_timegm(std::tm *tm)
+ {
+ std::time_t out;
+ std::string tz_backup;
+
+ ENV_TZ.lock();
+
+ // Store current value of env variable TZ
+ const char* tz_env_pointer = ::getenv("TZ");
+ if (tz_env_pointer != nullptr)
+ tz_backup = std::string(tz_env_pointer);
+
+ // Clear value of TZ
+ ::setenv("TZ", "", 1);
+ ::tzset();
+
+ out = ::mktime(tm);
+
+ // Restore TZ
+ if (!tz_backup.empty())
+ {
+ // setenv makes a copy of the second argument
+ ::setenv("TZ", tz_backup.data(), 1);
+ }
+ else
+ {
+ ::unsetenv("TZ");
+ }
+ ::tzset();
+
+ ENV_TZ.unlock();
+
+ return out;
+}
+#endif
+
}
std::chrono::system_clock::time_point calendar_point::to_std_timepoint()
{
- if (year < 1900)
+ if (year < 1970)
throw Invalid_Argument("calendar_point::to_std_timepoint() does not support years before 1990.");
// 32 bit time_t ends at January 19, 2038
@@ -48,7 +91,9 @@ std::chrono::system_clock::time_point calendar_point::to_std_timepoint()
if (year > 2037)
throw Invalid_Argument("calendar_point::to_std_timepoint() does not support years after 2037.");
+ // std::tm: struct without any timezone information
std::tm tm;
+ tm.tm_isdst = -1; // i.e. no DST information available
tm.tm_sec = seconds;
tm.tm_min = minutes;
tm.tm_hour = hour;
@@ -56,12 +101,18 @@ std::chrono::system_clock::time_point calendar_point::to_std_timepoint()
tm.tm_mon = month - 1;
tm.tm_year = year - 1900;
- // Convert std::tm to std::time_t
+ // Define a function alias `botan_timegm`
+ #if defined(BOTAN_TARGET_OS_HAS_TIMEGM)
+ std::time_t (&botan_timegm)(std::tm *tm) = timegm;
+ #elif defined(BOTAN_TARGET_OS_HAS_MKGMTIME)
// http://stackoverflow.com/questions/16647819/timegm-cross-platform
- #if defined(BOTAN_TARGET_OS_IS_WINDOWS)
- #define timegm _mkgmtime
+ std::time_t (&botan_timegm)(std::tm *tm) = _mkgmtime;
+ #else
+ std::time_t (&botan_timegm)(std::tm *tm) = fallback_timegm;
#endif
- std::time_t tt = timegm(&tm);
+
+ // Convert std::tm to std::time_t
+ std::time_t tt = botan_timegm(&tm);
if (tt == -1)
throw Invalid_Argument("calendar_point couldn't be converted: " + to_string());