chiark / gitweb /
Get rid of some more unused defines and dirs
[elogind.git] / src / shared / time-util.c
index fc79c569f4bceb52450a4a7be17ea09d6b8c817b..1c36c577c4af36c9255554831161c8e65cb26171 100644 (file)
@@ -22,6 +22,7 @@
 #include <time.h>
 #include <string.h>
 #include <sys/timex.h>
+#include <sys/timerfd.h>
 
 #include "util.h"
 #include "time-util.h"
@@ -48,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;
 }
@@ -75,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;
         }
 
@@ -97,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 +
@@ -110,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;
@@ -127,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 +
@@ -140,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 {
@@ -151,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;
@@ -191,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";
@@ -278,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;
         }
@@ -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;
@@ -740,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;
 
@@ -748,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;
@@ -920,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;
 
@@ -929,3 +974,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;
+}