X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Ftime-util.c;h=1c36c577c4af36c9255554831161c8e65cb26171;hp=76ab143f34990af69a5aef064de90fcc027fcb20;hb=8e8933ca0f06bae19cb6db601e83b33f8ac80f2a;hpb=77ff2de999b7ea6b1b4a3a218fbd9d62bb07cd54 diff --git a/src/shared/time-util.c b/src/shared/time-util.c index 76ab143f3..1c36c577c 100644 --- a/src/shared/time-util.c +++ b/src/shared/time-util.c @@ -49,25 +49,20 @@ 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 || u <= 0) { + ts->realtime = ts->monotonic = u; return ts; } ts->realtime = u; - if (u == 0) - ts->monotonic = 0; - else { - delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u; - - ts->monotonic = now(CLOCK_MONOTONIC); + delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u; + ts->monotonic = now(CLOCK_MONOTONIC); - if ((int64_t) ts->monotonic > delta) - ts->monotonic -= delta; - else - ts->monotonic = 0; - } + if ((int64_t) ts->monotonic > delta) + ts->monotonic -= delta; + else + ts->monotonic = 0; return ts; } @@ -76,8 +71,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; } @@ -98,10 +93,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 + @@ -111,7 +106,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; @@ -128,10 +123,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 + @@ -141,7 +136,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 { @@ -152,36 +147,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; @@ -192,15 +202,22 @@ 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; + n = now(CLOCK_REALTIME); if (n > t) { d = n - t; s = "ago"; @@ -279,11 +296,14 @@ 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 == USEC_INFINITY) { + strncpy(p, "infinity", l-1); + p[l-1] = 0; + return p; + } if (t <= 0) { - snprintf(p, l, "0"); + strncpy(p, "0", l-1); p[l-1] = 0; return p; } @@ -628,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; @@ -636,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; @@ -741,7 +773,7 @@ int parse_nsec(const char *t, nsec_t *nsec) { { "", 1ULL }, /* default is nsec */ }; - const char *p; + const char *p, *s; nsec_t r = 0; bool something = false; @@ -749,6 +781,18 @@ int parse_nsec(const char *t, nsec_t *nsec) { assert(nsec); p = t; + + p += strspn(p, WHITESPACE); + s = startswith(p, "infinity"); + if (s) { + s += strspn(s, WHITESPACE); + if (*s != 0) + return -EINVAL; + + *nsec = NSEC_INFINITY; + return 0; + } + for (;;) { long long l, z = 0; char *e; @@ -921,7 +965,7 @@ bool timezone_is_valid(const char *name) { if (slash) return false; - t = strappenda("/usr/share/zoneinfo/", name); + t = strjoina("/usr/share/zoneinfo/", name); if (stat(t, &st) < 0) return false;