chiark / gitweb /
load-fragment: allow timeout specifications such as '7min 5s'
authorLennart Poettering <lennart@poettering.net>
Fri, 23 Apr 2010 18:26:59 +0000 (20:26 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 23 Apr 2010 18:26:59 +0000 (20:26 +0200)
load-fragment.c
util.c
util.h

index 680f041..ff3b29c 100644 (file)
@@ -411,7 +411,6 @@ static int config_parse_usec(
                 void *userdata) {
 
         usec_t *usec = data;
-        unsigned long long u;
         int r;
 
         assert(filename);
@@ -419,17 +418,11 @@ static int config_parse_usec(
         assert(rvalue);
         assert(data);
 
-        if ((r = safe_atollu(rvalue, &u)) < 0) {
+        if ((r = parse_usec(rvalue, usec)) < 0) {
                 log_error("[%s:%u] Failed to parse time value: %s", filename, line, rvalue);
                 return r;
         }
 
-        /* We actually assume the user configures seconds. Later on we
-         * might choose to support suffixes for time values, to
-         * configure bigger or smaller units */
-
-        *usec = u * USEC_PER_SEC;
-
         return 0;
 }
 
diff --git a/util.c b/util.c
index e9f7813..83e819a 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1776,6 +1776,69 @@ int path_is_mount_point(const char *t) {
         return a.st_dev != b.st_dev;
 }
 
+int parse_usec(const char *t, usec_t *usec) {
+        static const struct {
+                const char *suffix;
+                usec_t usec;
+        } table[] = {
+                { "sec", USEC_PER_SEC },
+                { "s", USEC_PER_SEC },
+                { "min", USEC_PER_MINUTE },
+                { "hr", USEC_PER_HOUR },
+                { "h", USEC_PER_HOUR },
+                { "d", USEC_PER_DAY },
+                { "w", USEC_PER_WEEK },
+                { "msec", USEC_PER_MSEC },
+                { "ms", USEC_PER_MSEC },
+                { "m", USEC_PER_MINUTE },
+                { "usec", 1ULL },
+                { "us", 1ULL },
+                { "", USEC_PER_SEC },
+        };
+
+        const char *p;
+        usec_t r = 0;
+
+        assert(t);
+        assert(usec);
+
+        p = t;
+        do {
+                long long l;
+                char *e;
+                unsigned i;
+
+                errno = 0;
+                l = strtoll(p, &e, 10);
+
+                if (errno != 0)
+                        return -errno;
+
+                if (l < 0)
+                        return -ERANGE;
+
+                if (e == p)
+                        return -EINVAL;
+
+                e += strspn(e, WHITESPACE);
+
+                for (i = 0; i < ELEMENTSOF(table); i++)
+                        if (startswith(e, table[i].suffix)) {
+                                r += (usec_t) l * table[i].usec;
+                                p = e + strlen(table[i].suffix);
+                                break;
+                        }
+
+                if (i >= ELEMENTSOF(table))
+                        return -EINVAL;
+
+        } while (*p != 0);
+
+        *usec = r;
+
+        return 0;
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",
diff --git a/util.h b/util.h
index 0ef3df6..ecf3b15 100644 (file)
--- a/util.h
+++ b/util.h
@@ -38,6 +38,11 @@ typedef uint64_t usec_t;
 #define NSEC_PER_MSEC 1000000ULL
 #define NSEC_PER_USEC 1000ULL
 
+#define USEC_PER_MINUTE (60ULL*USEC_PER_SEC)
+#define USEC_PER_HOUR (60ULL*USEC_PER_MINUTE)
+#define USEC_PER_DAY (24ULL*USEC_PER_HOUR)
+#define USEC_PER_WEEK (7ULL*USEC_PER_DAY)
+
 /* What is interpreted as whitespace? */
 #define WHITESPACE " \t\n\r"
 #define NEWLINE "\n\r"
@@ -91,6 +96,7 @@ int close_nointr(int fd);
 void close_nointr_nofail(int fd);
 
 int parse_boolean(const char *v);
+int parse_usec(const char *t, usec_t *usec);
 
 int safe_atou(const char *s, unsigned *ret_u);
 int safe_atoi(const char *s, int *ret_i);