diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/util.c | 78 | ||||
-rw-r--r-- | src/common/util.h | 3 |
2 files changed, 55 insertions, 26 deletions
diff --git a/src/common/util.c b/src/common/util.c index feeaf740b2..4e203e7de1 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -332,9 +332,9 @@ tor_mathlog(double d) return log(d); } -/** Return the long integer closest to d. We define this wrapper here so - * that not all users of math.h need to use the right incancations to get - * the c99 functions. */ +/** Return the long integer closest to <b>d</b>. We define this wrapper + * here so that not all users of math.h need to use the right incantations + * to get the c99 functions. */ long tor_lround(double d) { @@ -347,6 +347,21 @@ tor_lround(double d) #endif } +/** Return the 64-bit integer closest to d. We define this wrapper here so + * that not all users of math.h need to use the right incantations to get the + * c99 functions. */ +int64_t +tor_llround(double d) +{ +#if defined(HAVE_LLROUND) + return (int64_t)llround(d); +#elif defined(HAVE_RINT) + return (int64_t)rint(d); +#else + return (int64_t)(d > 0 ? d + 0.5 : ceil(d - 0.5)); +#endif +} + /** Returns floor(log2(u64)). If u64 is 0, (incorrectly) returns 0. */ int tor_log2(uint64_t u64) @@ -379,12 +394,24 @@ tor_log2(uint64_t u64) return r; } -/** Return the power of 2 closest to <b>u64</b>. */ +/** Return the power of 2 in range [1,UINT64_MAX] closest to <b>u64</b>. If + * there are two powers of 2 equally close, round down. */ uint64_t round_to_power_of_2(uint64_t u64) { - int lg2 = tor_log2(u64); - uint64_t low = U64_LITERAL(1) << lg2, high = U64_LITERAL(1) << (lg2+1); + int lg2; + uint64_t low; + uint64_t high; + if (u64 == 0) + return 1; + + lg2 = tor_log2(u64); + low = U64_LITERAL(1) << lg2; + + if (lg2 == 63) + return low; + + high = U64_LITERAL(1) << (lg2+1); if (high - u64 < u64 - low) return high; else @@ -1315,11 +1342,11 @@ n_leapdays(int y1, int y2) static const int days_per_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -/** Return a time_t given a struct tm. The result is given in GMT, and - * does not account for leap seconds. +/** Compute a time_t given a struct tm. The result is given in GMT, and + * does not account for leap seconds. Return 0 on success, -1 on failure. */ -time_t -tor_timegm(struct tm *tm) +int +tor_timegm(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(). @@ -1327,11 +1354,11 @@ tor_timegm(struct tm *tm) time_t year, days, hours, minutes, seconds; int i; year = tm->tm_year + 1900; - if (year < 1970 || tm->tm_mon < 0 || tm->tm_mon > 11) { + if (year < 1970 || tm->tm_mon < 0 || tm->tm_mon > 11 || + tm->tm_year >= INT32_MAX-1900) { log_warn(LD_BUG, "Out-of-range argument to tor_timegm"); return -1; } - tor_assert(year < INT_MAX); days = 365 * (year-1970) + n_leapdays(1970,(int)year); for (i = 0; i < tm->tm_mon; ++i) days += days_per_month[i]; @@ -1342,7 +1369,8 @@ tor_timegm(struct tm *tm) minutes = hours*60 + tm->tm_min; seconds = minutes*60 + tm->tm_sec; - return seconds; + *time_out = seconds; + return 0; } /* strftime is locale-specific, so we need to replace those parts */ @@ -1402,7 +1430,7 @@ parse_rfc1123_time(const char *buf, time_t *t) return -1; } if (tm_mday < 1 || tm_mday > 31 || tm_hour > 23 || tm_min > 59 || - tm_sec > 60) { + tm_sec > 60 || tm_year >= INT32_MAX || tm_year < 1970) { char *esc = esc_for_log(buf); log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc); tor_free(esc); @@ -1438,8 +1466,7 @@ parse_rfc1123_time(const char *buf, time_t *t) } tm.tm_year -= 1900; - *t = tor_timegm(&tm); - return 0; + return tor_timegm(&tm, t); } /** Set <b>buf</b> to the ISO8601 encoding of the local value of <b>t</b>. @@ -1501,13 +1528,13 @@ parse_iso_time(const char *cp, time_t *t) return -1; } if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || - hour > 23 || minute > 59 || second > 60) { + hour > 23 || minute > 59 || second > 60 || year >= INT32_MAX) { char *esc = esc_for_log(cp); log_warn(LD_GENERAL, "ISO time %s was nonsensical", esc); tor_free(esc); return -1; } - st_tm.tm_year = year-1900; + st_tm.tm_year = (int)year-1900; st_tm.tm_mon = month-1; st_tm.tm_mday = day; st_tm.tm_hour = hour; @@ -1520,8 +1547,7 @@ parse_iso_time(const char *cp, time_t *t) tor_free(esc); return -1; } - *t = tor_timegm(&st_tm); - return 0; + return tor_timegm(&st_tm, t); } /** Given a <b>date</b> in one of the three formats allowed by HTTP (ugh), @@ -2362,7 +2388,7 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out) } string[r] = '\0'; /* NUL-terminate the result. */ -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) if (!bin && strchr(string, '\r')) { log_debug(LD_FS, "We didn't convert CRLF to LF as well as we hoped " "when reading %s. Coping.", @@ -3957,13 +3983,15 @@ tor_process_handle_destroy(process_handle_t *process_handle, if (also_terminate_process) { if (tor_terminate_process(process_handle) < 0) { - log_notice(LD_GENERAL, "Failed to terminate process with " - "PID '%d' ('%s').", tor_process_get_pid(process_handle), + const char *errstr = #ifdef _WIN32 - format_win32_error(GetLastError())); + format_win32_error(GetLastError()); #else - strerror(errno)); + strerror(errno); #endif + log_notice(LD_GENERAL, "Failed to terminate process with " + "PID '%d' ('%s').", tor_process_get_pid(process_handle), + errstr); } else { log_info(LD_GENERAL, "Terminated process with PID '%d'.", tor_process_get_pid(process_handle)); diff --git a/src/common/util.h b/src/common/util.h index 0cfc1b9d89..6667978d18 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -160,6 +160,7 @@ void tor_log_mallinfo(int severity); /* Math functions */ double tor_mathlog(double d) ATTR_CONST; long tor_lround(double d) ATTR_CONST; +int64_t tor_llround(double d) ATTR_CONST; int tor_log2(uint64_t u64) ATTR_CONST; uint64_t round_to_power_of_2(uint64_t u64); unsigned round_to_next_multiple_of(unsigned number, unsigned divisor); @@ -244,7 +245,7 @@ int64_t tv_to_msec(const struct timeval *tv); int64_t tv_to_usec(const struct timeval *tv); long tv_udiff(const struct timeval *start, const struct timeval *end); long tv_mdiff(const struct timeval *start, const struct timeval *end); -time_t tor_timegm(struct tm *tm); +int tor_timegm(const struct tm *tm, time_t *time_out); #define RFC1123_TIME_LEN 29 void format_rfc1123_time(char *buf, time_t t); int parse_rfc1123_time(const char *buf, time_t *t); |