summaryrefslogtreecommitdiff
path: root/src/common/compat.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-06-22 11:07:10 -0400
committerNick Mathewson <nickm@torproject.org>2018-06-22 11:17:11 -0400
commitbfb39164ce49450fad11611a129dd875acebde54 (patch)
tree49584d2dda75ed86278d3e93a4dff19f8d039d20 /src/common/compat.c
parentb2d4e786b7ed2563461513e36c7e75bea1f70be8 (diff)
downloadtor-bfb39164ce49450fad11611a129dd875acebde54.tar.gz
tor-bfb39164ce49450fad11611a129dd875acebde54.zip
Extract core part of gmtime_r, localtime_r (without logging)
Diffstat (limited to 'src/common/compat.c')
-rw-r--r--src/common/compat.c172
1 files changed, 15 insertions, 157 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index b4175c15ab..351fa05634 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -127,6 +127,7 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt)
#include "lib/log/torlog.h"
#include "common/util.h"
#include "lib/container/smartlist.h"
+#include "lib/wallclock/tm_cvt.h"
#include "common/address.h"
#include "common/sandbox.h"
@@ -2648,183 +2649,40 @@ compute_num_cpus(void)
return num_cpus;
}
-#if !defined(_WIN32)
-/** Defined iff we need to add locks when defining fake versions of reentrant
- * versions of time-related functions. */
-#define TIME_FNS_NEED_LOCKS
-#endif
-
-/** Helper: Deal with confused or out-of-bounds values from localtime_r and
- * friends. (On some platforms, they can give out-of-bounds values or can
- * return NULL.) If <b>islocal</b>, this is a localtime result; otherwise
- * it's from gmtime. The function returns <b>r</b>, when given <b>timep</b>
- * as its input. If we need to store new results, store them in
- * <b>resultbuf</b>. */
-static struct tm *
-correct_tm(int islocal, const time_t *timep, struct tm *resultbuf,
- struct tm *r)
-{
- const char *outcome;
-
- if (PREDICT_LIKELY(r)) {
- /* We can't strftime dates after 9999 CE, and we want to avoid dates
- * before 1 CE (avoiding the year 0 issue and negative years). */
- if (r->tm_year > 8099) {
- r->tm_year = 8099;
- r->tm_mon = 11;
- r->tm_mday = 31;
- r->tm_yday = 364;
- r->tm_wday = 6;
- r->tm_hour = 23;
- r->tm_min = 59;
- r->tm_sec = 59;
- } else if (r->tm_year < (1-1900)) {
- r->tm_year = (1-1900);
- r->tm_mon = 0;
- r->tm_mday = 1;
- r->tm_yday = 0;
- r->tm_wday = 0;
- r->tm_hour = 0;
- r->tm_min = 0;
- r->tm_sec = 0;
- }
- return r;
- }
-
- /* If we get here, gmtime or localtime returned NULL. It might have done
- * this because of overrun or underrun, or it might have done it because of
- * some other weird issue. */
- if (timep) {
- if (*timep < 0) {
- r = resultbuf;
- r->tm_year = 70; /* 1970 CE */
- r->tm_mon = 0;
- r->tm_mday = 1;
- r->tm_yday = 0;
- r->tm_wday = 0;
- r->tm_hour = 0;
- r->tm_min = 0 ;
- r->tm_sec = 0;
- outcome = "Rounding up to 1970";
- goto done;
- } else if (*timep >= INT32_MAX) {
- /* Rounding down to INT32_MAX isn't so great, but keep in mind that we
- * only do it if gmtime/localtime tells us NULL. */
- r = resultbuf;
- r->tm_year = 137; /* 2037 CE */
- r->tm_mon = 11;
- r->tm_mday = 31;
- r->tm_yday = 364;
- r->tm_wday = 6;
- r->tm_hour = 23;
- r->tm_min = 59;
- r->tm_sec = 59;
- outcome = "Rounding down to 2037";
- goto done;
- }
- }
-
- /* If we get here, then gmtime/localtime failed without getting an extreme
- * value for *timep */
- /* LCOV_EXCL_START */
- tor_fragile_assert();
- r = resultbuf;
- memset(resultbuf, 0, sizeof(struct tm));
- outcome="can't recover";
- /* LCOV_EXCL_STOP */
- done:
- log_warn(LD_BUG, "%s("I64_FORMAT") failed with error %s: %s",
- islocal?"localtime":"gmtime",
- timep?I64_PRINTF_ARG(*timep):0,
- strerror(errno),
- outcome);
- return r;
-}
-/** @{ */
/** As localtime_r, but defined for platforms that don't have it:
*
* Convert *<b>timep</b> to a struct tm in local time, and store the value in
* *<b>result</b>. Return the result on success, or NULL on failure.
*/
-#ifdef HAVE_LOCALTIME_R
struct tm *
tor_localtime_r(const time_t *timep, struct tm *result)
{
- struct tm *r;
- r = localtime_r(timep, result);
- return correct_tm(1, timep, result, r);
-}
-#elif defined(TIME_FNS_NEED_LOCKS)
-struct tm *
-tor_localtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- static tor_mutex_t *m=NULL;
- if (!m) { m=tor_mutex_new(); }
- tor_assert(result);
- tor_mutex_acquire(m);
- r = localtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- tor_mutex_release(m);
- return correct_tm(1, timep, result, r);
-}
-#else
-struct tm *
-tor_localtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- tor_assert(result);
- r = localtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- return correct_tm(1, timep, result, r);
+ char *err = NULL;
+ struct tm *r = tor_localtime_r_msg(timep, result, &err);
+ if (err) {
+ log_warn(LD_BUG, "%s", err);
+ tor_free(err);
+ }
+ return r;
}
-#endif /* defined(HAVE_LOCALTIME_R) || ... */
-/** @} */
-/** @{ */
/** As gmtime_r, but defined for platforms that don't have it:
*
* Convert *<b>timep</b> to a struct tm in UTC, and store the value in
* *<b>result</b>. Return the result on success, or NULL on failure.
*/
-#ifdef HAVE_GMTIME_R
struct tm *
tor_gmtime_r(const time_t *timep, struct tm *result)
{
- struct tm *r;
- r = gmtime_r(timep, result);
- return correct_tm(0, timep, result, r);
-}
-#elif defined(TIME_FNS_NEED_LOCKS)
-struct tm *
-tor_gmtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- static tor_mutex_t *m=NULL;
- if (!m) { m=tor_mutex_new(); }
- tor_assert(result);
- tor_mutex_acquire(m);
- r = gmtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- tor_mutex_release(m);
- return correct_tm(0, timep, result, r);
-}
-#else
-struct tm *
-tor_gmtime_r(const time_t *timep, struct tm *result)
-{
- struct tm *r;
- tor_assert(result);
- r = gmtime(timep);
- if (r)
- memcpy(result, r, sizeof(struct tm));
- return correct_tm(0, timep, result, r);
+ char *err = NULL;
+ struct tm *r = tor_gmtime_r_msg(timep, result, &err);
+ if (err) {
+ log_warn(LD_BUG, "%s", err);
+ tor_free(err);
+ }
+ return r;
}
-#endif /* defined(HAVE_GMTIME_R) || ... */
#if defined(HAVE_MLOCKALL) && HAVE_DECL_MLOCKALL && defined(RLIMIT_MEMLOCK)
#define HAVE_UNIX_MLOCKALL