X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Ftime-util.c;h=433c262dfad1b1d66056e14c84d68d5558b92e49;hb=5ab99e076c72a44f2e174e48abd9945cd0180d76;hp=fc79c569f4bceb52450a4a7be17ea09d6b8c817b;hpb=7568345034f2890af745747783c5abfbf6eccf0f;p=elogind.git diff --git a/src/shared/time-util.c b/src/shared/time-util.c index fc79c569f..433c262df 100644 --- a/src/shared/time-util.c +++ b/src/shared/time-util.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "util.h" #include "time-util.h" @@ -48,8 +49,8 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) { int64_t delta; assert(ts); - if (u == (usec_t) -1) { - ts->realtime = ts->monotonic = (usec_t) -1; + if (u == USEC_INFINITY) { + ts->realtime = ts->monotonic = USEC_INFINITY; return ts; } @@ -75,8 +76,8 @@ dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) { int64_t delta; assert(ts); - if (u == (usec_t) -1) { - ts->realtime = ts->monotonic = (usec_t) -1; + if (u == USEC_INFINITY) { + ts->realtime = ts->monotonic = USEC_INFINITY; return ts; } @@ -97,10 +98,10 @@ usec_t timespec_load(const struct timespec *ts) { if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1) - return (usec_t) -1; + return USEC_INFINITY; if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) - return (usec_t) -1; + return USEC_INFINITY; return (usec_t) ts->tv_sec * USEC_PER_SEC + @@ -110,7 +111,7 @@ usec_t timespec_load(const struct timespec *ts) { struct timespec *timespec_store(struct timespec *ts, usec_t u) { assert(ts); - if (u == (usec_t) -1) { + if (u == USEC_INFINITY) { ts->tv_sec = (time_t) -1; ts->tv_nsec = (long) -1; return ts; @@ -127,10 +128,10 @@ usec_t timeval_load(const struct timeval *tv) { if (tv->tv_sec == (time_t) -1 && tv->tv_usec == (suseconds_t) -1) - return (usec_t) -1; + return USEC_INFINITY; if ((usec_t) tv->tv_sec > (UINT64_MAX - tv->tv_usec) / USEC_PER_SEC) - return (usec_t) -1; + return USEC_INFINITY; return (usec_t) tv->tv_sec * USEC_PER_SEC + @@ -140,7 +141,7 @@ usec_t timeval_load(const struct timeval *tv) { struct timeval *timeval_store(struct timeval *tv, usec_t u) { assert(tv); - if (u == (usec_t) -1) { + if (u == USEC_INFINITY) { tv->tv_sec = (time_t) -1; tv->tv_usec = (suseconds_t) -1; } else { @@ -151,36 +152,51 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) { return tv; } -char *format_timestamp(char *buf, size_t l, usec_t t) { +static char *format_timestamp_internal(char *buf, size_t l, usec_t t, bool utc) { struct tm tm; time_t sec; assert(buf); assert(l > 0); - if (t <= 0 || t == (usec_t) -1) + if (t <= 0 || t == USEC_INFINITY) return NULL; sec = (time_t) (t / USEC_PER_SEC); - if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) <= 0) + if (utc) + gmtime_r(&sec, &tm); + else + localtime_r(&sec, &tm); + if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm) <= 0) return NULL; return buf; } -char *format_timestamp_us(char *buf, size_t l, usec_t t) { +char *format_timestamp(char *buf, size_t l, usec_t t) { + return format_timestamp_internal(buf, l, t, false); +} + +char *format_timestamp_utc(char *buf, size_t l, usec_t t) { + return format_timestamp_internal(buf, l, t, true); +} + +static char *format_timestamp_internal_us(char *buf, size_t l, usec_t t, bool utc) { struct tm tm; time_t sec; assert(buf); assert(l > 0); - if (t <= 0 || t == (usec_t) -1) + if (t <= 0 || t == USEC_INFINITY) return NULL; sec = (time_t) (t / USEC_PER_SEC); - localtime_r(&sec, &tm); + if (utc) + gmtime_r(&sec, &tm); + else + localtime_r(&sec, &tm); if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm) <= 0) return NULL; @@ -191,13 +207,21 @@ char *format_timestamp_us(char *buf, size_t l, usec_t t) { return buf; } +char *format_timestamp_us(char *buf, size_t l, usec_t t) { + return format_timestamp_internal_us(buf, l, t, false); +} + +char *format_timestamp_us_utc(char *buf, size_t l, usec_t t) { + return format_timestamp_internal_us(buf, l, t, true); +} + char *format_timestamp_relative(char *buf, size_t l, usec_t t) { const char *s; usec_t n, d; n = now(CLOCK_REALTIME); - if (t <= 0 || (t == (usec_t) -1)) + if (t <= 0 || (t == USEC_INFINITY)) return NULL; if (n > t) { @@ -278,11 +302,8 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) { assert(buf); assert(l > 0); - if (t == (usec_t) -1) - return NULL; - - if (t <= 0) { - snprintf(p, l, "0"); + if (t == USEC_INFINITY || t <= 0) { + strncpy(p, t == USEC_INFINITY ? "infinity" : "0", l); p[l-1] = 0; return p; } @@ -627,7 +648,7 @@ int parse_sec(const char *t, usec_t *usec) { { "", USEC_PER_SEC }, /* default is sec */ }; - const char *p; + const char *p, *s; usec_t r = 0; bool something = false; @@ -635,6 +656,18 @@ int parse_sec(const char *t, usec_t *usec) { assert(usec); p = t; + + p += strspn(p, WHITESPACE); + s = startswith(p, "infinity"); + if (s) { + s += strspn(s, WHITESPACE); + if (*s != 0) + return -EINVAL; + + *usec = USEC_INFINITY; + return 0; + } + for (;;) { long long l, z = 0; char *e; @@ -929,3 +962,21 @@ bool timezone_is_valid(const char *name) { return true; } + +clockid_t clock_boottime_or_monotonic(void) { + static clockid_t clock = -1; + int fd; + + if (clock != -1) + return clock; + + fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC); + if (fd < 0) + clock = CLOCK_MONOTONIC; + else { + safe_close(fd); + clock = CLOCK_BOOTTIME; + } + + return clock; +}