summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-04-23 20:26:59 +0200
committerLennart Poettering <lennart@poettering.net>2010-04-23 20:26:59 +0200
commit24a6e4a401f0be0c4cd67621186792d0b7e401a1 (patch)
tree4eb964777415835d384bfc45e814980a8a0a2f73
parent40d50879d9339e539a30e5d32234baffb732f0f9 (diff)
load-fragment: allow timeout specifications such as '7min 5s'
-rw-r--r--load-fragment.c9
-rw-r--r--util.c63
-rw-r--r--util.h6
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;
}
diff --git a/util.c b/util.c
index e9f7813b8b..83e819a0cb 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 0ef3df6d57..ecf3b15e33 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);