summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGeorge Kadianakis <desnacked@riseup.net>2021-07-06 13:42:53 +0300
committerGeorge Kadianakis <desnacked@riseup.net>2021-07-06 13:42:53 +0300
commit167f3bc4ecbe4f0265413f3a1b91b6faab1c0f81 (patch)
tree394375d616c7fd7e977fdcd6528f6d48dcf897c8 /src
parent2758ae30b32cc75843cf216a310447eac4bdf7ac (diff)
parent98b9df61f6f2d33dab857b1e7d2f8e848678f5ed (diff)
downloadtor-167f3bc4ecbe4f0265413f3a1b91b6faab1c0f81.tar.gz
tor-167f3bc4ecbe4f0265413f3a1b91b6faab1c0f81.zip
Merge branch 'maint-0.4.5' into maint-0.4.6
Diffstat (limited to 'src')
-rw-r--r--src/lib/encoding/time_fmt.c35
-rw-r--r--src/lib/encoding/time_fmt.h6
-rw-r--r--src/test/test_util.c26
3 files changed, 64 insertions, 3 deletions
diff --git a/src/lib/encoding/time_fmt.c b/src/lib/encoding/time_fmt.c
index b170ddfc12..136158ab1b 100644
--- a/src/lib/encoding/time_fmt.c
+++ b/src/lib/encoding/time_fmt.c
@@ -13,6 +13,7 @@
* and handles a larger variety of types. It converts between different time
* formats, and encodes and decodes them from strings.
**/
+#define TIME_FMT_PRIVATE
#include "lib/encoding/time_fmt.h"
#include "lib/log/log.h"
@@ -25,6 +26,7 @@
#include <string.h>
#include <time.h>
+#include <errno.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
@@ -92,8 +94,8 @@ static const int days_per_month[] =
/** Compute a time_t given a struct tm. The result is given in UTC, and
* does not account for leap seconds. Return 0 on success, -1 on failure.
*/
-int
-tor_timegm(const struct tm *tm, time_t *time_out)
+ATTR_UNUSED STATIC int
+tor_timegm_impl(const struct tm *tm, time_t *time_out)
{
/* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
* It's way more brute-force than fiddling with tzset().
@@ -162,6 +164,35 @@ tor_timegm(const struct tm *tm, time_t *time_out)
return 0;
}
+/** Compute a time_t given a struct tm. The result here should be an inverse
+ * of the system's gmtime() function. Return 0 on success, -1 on failure.
+ */
+int
+tor_timegm(const struct tm *tm, time_t *time_out)
+{
+#ifdef HAVE_TIMEGM
+ /* If the system gives us a timegm(), use it: if the system's time_t
+ * includes leap seconds, then we can hope that its timegm() knows too.
+ *
+ * https://k5wiki.kerberos.org/wiki/Leap_second_handling says the in
+ * general we can rely on any system with leap seconds also having a
+ * timegm implementation. Let's hope it's right!
+ * */
+ time_t result = timegm((struct tm *) tm);
+ if (result == -1) {
+ log_warn(LD_BUG, "timegm() could not convert time: %s", strerror(errno));
+ *time_out = 0;
+ return -1;
+ } else {
+ *time_out = result;
+ return 0;
+ }
+#else
+ /* The system doesn't have timegm; we'll have to use our own. */
+ return tor_timegm_impl(tm, time_out);
+#endif
+}
+
/* strftime is locale-specific, so we need to replace those parts */
/** A c-locale array of 3-letter names of weekdays, starting with Sun. */
diff --git a/src/lib/encoding/time_fmt.h b/src/lib/encoding/time_fmt.h
index df38442e9b..aaf8ba7af0 100644
--- a/src/lib/encoding/time_fmt.h
+++ b/src/lib/encoding/time_fmt.h
@@ -18,6 +18,8 @@
#include <sys/types.h>
#endif
+#include "lib/testsupport/testsupport.h"
+
struct tm;
struct timeval;
@@ -41,4 +43,8 @@ int parse_iso_time_nospace(const char *cp, time_t *t);
int parse_http_time(const char *buf, struct tm *tm);
int format_time_interval(char *out, size_t out_len, long interval);
+#ifdef TIME_FMT_PRIVATE
+STATIC int tor_timegm_impl(const struct tm *tm, time_t *time_out);
+#endif
+
#endif /* !defined(TOR_TIME_FMT_H) */
diff --git a/src/test/test_util.c b/src/test/test_util.c
index f10aed71ac..291a97d52b 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -7,6 +7,7 @@
#define COMPAT_TIME_PRIVATE
#define UTIL_MALLOC_PRIVATE
#define PROCESS_WIN32_PRIVATE
+#define TIME_FMT_PRIVATE
#include "lib/testsupport/testsupport.h"
#include "core/or/or.h"
#include "lib/buf/buffers.h"
@@ -111,7 +112,7 @@ static time_t
tor_timegm_wrapper(const struct tm *tm)
{
time_t t;
- if (tor_timegm(tm, &t) < 0)
+ if (tor_timegm_impl(tm, &t) < 0)
return -1;
return t;
}
@@ -1502,6 +1503,28 @@ test_util_parse_http_time(void *arg)
}
static void
+test_util_timegm_real(void *arg)
+{
+ (void)arg;
+ /* Get the real timegm again! We're not testing our impl; we want the
+ * one that will actually get called. */
+#undef tor_timegm
+
+ /* Now check: is timegm the real inverse of gmtime? */
+ time_t now = time(NULL), time2=0;
+ struct tm tm, *p;
+ p = tor_gmtime_r(&now, &tm);
+ tt_ptr_op(p, OP_NE, NULL);
+
+ int r = tor_timegm(&tm, &time2);
+ tt_int_op(r, OP_EQ, 0);
+ tt_i64_op((int64_t) now, OP_EQ, (int64_t) time2);
+
+ done:
+ ;
+}
+
+static void
test_util_config_line(void *arg)
{
char buf[1024];
@@ -7036,6 +7059,7 @@ struct testcase_t util_tests[] = {
UTIL_TEST(monotonic_time_ratchet, TT_FORK),
UTIL_TEST(monotonic_time_zero, 0),
UTIL_TEST(monotonic_time_add_msec, 0),
+ UTIL_TEST(timegm_real, 0),
UTIL_TEST(htonll, 0),
UTIL_TEST(get_unquoted_path, 0),
UTIL_TEST(map_anon, 0),