From: Lennart Poettering Date: Fri, 23 Apr 2010 18:26:59 +0000 (+0200) Subject: load-fragment: allow timeout specifications such as '7min 5s' X-Git-Tag: v1~475 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=24a6e4a401f0be0c4cd67621186792d0b7e401a1 load-fragment: allow timeout specifications such as '7min 5s' --- diff --git a/load-fragment.c b/load-fragment.c index 680f04171..ff3b29c08 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; } diff --git a/util.c b/util.c index e9f7813b8..83e819a0c 100644 --- 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 0ef3df6d5..ecf3b15e3 100644 --- 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);