diff --git a/src/common/util.c b/src/common/util.c index c44a4aa3b1..e7059a5bd9 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1430,6 +1430,26 @@ format_iso_time(char *buf, time_t t) strftime(buf, ISO_TIME_LEN+1, "%Y-%m-%d %H:%M:%S", tor_gmtime_r(&t, &tm)); } +/** As format_iso_time, but use the yyyy-mm-ddThh:mm:ss format to avoid + * embedding an internal space. */ +void +format_iso_time_nospace(char *buf, time_t t) +{ + format_iso_time(buf, t); + buf[10] = 'T'; +} + +/** As format_iso_time_nospace, but include microseconds in decimal + * fixed-point format. Requires that buf be at least ISO_TIME_USEC_LEN+1 + * bytes long. */ +void +format_iso_time_nospace_usec(char *buf, const struct timeval *tv) +{ + tor_assert(tv); + format_iso_time_nospace(buf, tv->tv_sec); + tor_snprintf(buf+ISO_TIME_LEN, 8, ".%06d", (int)tv->tv_usec); +} + /** Given an ISO-formatted UTC time value (after the epoch) in cp, * parse it and store its value in *t. Return 0 on success, -1 on * failure. Ignore extraneous stuff in cp separated by whitespace from diff --git a/src/common/util.h b/src/common/util.h index 77ed1ca5ee..bd471e3816 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -242,8 +242,11 @@ time_t tor_timegm(struct tm *tm); void format_rfc1123_time(char *buf, time_t t); int parse_rfc1123_time(const char *buf, time_t *t); #define ISO_TIME_LEN 19 +#define ISO_TIME_USEC_LEN (ISO_TIME_LEN+7) void format_local_iso_time(char *buf, time_t t); void format_iso_time(char *buf, time_t t); +void format_iso_time_nospace(char *buf, time_t t); +void format_iso_time_nospace_usec(char *buf, const struct timeval *tv); int parse_iso_time(const char *buf, 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); diff --git a/src/or/control.c b/src/or/control.c index e15adbd8e8..364cf9905c 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1853,10 +1853,10 @@ circuit_describe_status_for_controller(origin_circuit_t *circ) { char *time_created_arg = NULL; + char tbuf[ISO_TIME_USEC_LEN+1]; + format_iso_time_nospace_usec(tbuf, &circ->_base.timestamp_created); - tor_asprintf(&time_created_arg, "TIME_CREATED=%ld,%ld", - circ->_base.timestamp_created.tv_sec, - circ->_base.timestamp_created.tv_usec); + tor_asprintf(&time_created_arg, "TIME_CREATED=%s", tbuf); smartlist_add(descparts, time_created_arg); } diff --git a/src/test/test_util.c b/src/test/test_util.c index 64bf52e7b1..d549e235b6 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -19,9 +19,10 @@ test_util_time(void) { struct timeval start, end; struct tm a_time; - char timestr[RFC1123_TIME_LEN+1]; + char timestr[128]; time_t t_res; int i; + struct timeval tv; start.tv_sec = 5; start.tv_usec = 5000; @@ -83,6 +84,24 @@ test_util_time(void) /* We might've timewarped a little. */ tt_int_op(tv_udiff(&start, &end), >=, -5000); + /* Now let's check some format_iso_time variants */ + tv.tv_sec = (time_t)1326296338; + tv.tv_usec = 3060; + format_iso_time(timestr, tv.tv_sec); + test_streq("2012-01-11 15:38:58", timestr); + /* The output of format_local_iso_time will vary by timezone, and setting + our timezone for testing purposes would be a nontrivial flaky pain. + Skip this test for now. + format_local_iso_time(timestr, tv.tv_sec); + test_streq("2012-01-11 10:38:58", timestr); + */ + format_iso_time_nospace(timestr, tv.tv_sec); + test_streq("2012-01-11T15:38:58", timestr); + test_eq(strlen(timestr), ISO_TIME_LEN); + format_iso_time_nospace_usec(timestr, &tv); + test_streq("2012-01-11T15:38:58.003060", timestr); + test_eq(strlen(timestr), ISO_TIME_USEC_LEN); + done: ; }