diff options
author | Lennart Poettering <lennart@poettering.net> | 2010-04-23 20:26:59 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2010-04-23 20:26:59 +0200 |
commit | 24a6e4a401f0be0c4cd67621186792d0b7e401a1 (patch) | |
tree | 4eb964777415835d384bfc45e814980a8a0a2f73 | |
parent | 40d50879d9339e539a30e5d32234baffb732f0f9 (diff) |
load-fragment: allow timeout specifications such as '7min 5s'
-rw-r--r-- | load-fragment.c | 9 | ||||
-rw-r--r-- | util.c | 63 | ||||
-rw-r--r-- | util.h | 6 |
3 files changed, 70 insertions, 8 deletions
diff --git a/load-fragment.c b/load-fragment.c index 680f04171f..ff3b29c084 100644 --- a/load-fragment.c +++ b/load-fragment.c @@ -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; } @@ -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", @@ -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); |