summaryrefslogtreecommitdiff
path: root/src/shared/time-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-04-03 22:58:41 +0200
committerLennart Poettering <lennart@poettering.net>2013-04-03 23:00:08 +0200
commitcb0dac0548e5e51ba21618bfe4711dc1a2bbcfb5 (patch)
treea8b69c2b2507378c89cdb37ebe0683da34832c5e /src/shared/time-util.c
parentd3b9e0ff4e9f1b0bb328dc57ca5507bac48a6615 (diff)
downloadsystemd-cb0dac0548e5e51ba21618bfe4711dc1a2bbcfb5.tar.gz
time: add suppot for fractional time specifications
We can now parse "0.5s" as the same as "500ms". In fact, we can parse "3.45years" correctly, too, and any other unit and fraction length.
Diffstat (limited to 'src/shared/time-util.c')
-rw-r--r--src/shared/time-util.c90
1 files changed, 78 insertions, 12 deletions
diff --git a/src/shared/time-util.c b/src/shared/time-util.c
index e27aaf6c6a..476b847ead 100644
--- a/src/shared/time-util.c
+++ b/src/shared/time-util.c
@@ -534,15 +534,25 @@ int parse_sec(const char *t, usec_t *usec) {
const char *p;
usec_t r = 0;
+ bool something = false;
assert(t);
assert(usec);
p = t;
- do {
- long long l;
+ for (;;) {
+ long long l, z = 0;
char *e;
- unsigned i;
+ unsigned i, n = 0;
+
+ p += strspn(p, WHITESPACE);
+
+ if (*p == 0) {
+ if (!something)
+ return -EINVAL;
+
+ break;
+ }
errno = 0;
l = strtoll(p, &e, 10);
@@ -553,22 +563,45 @@ int parse_sec(const char *t, usec_t *usec) {
if (l < 0)
return -ERANGE;
- if (e == p)
+ if (*e == '.') {
+ char *b = e + 1;
+
+ errno = 0;
+ z = strtoll(b, &e, 10);
+ if (errno > 0)
+ return -errno;
+
+ if (z < 0)
+ return -ERANGE;
+
+ if (e == b)
+ return -EINVAL;
+
+ n = e - b;
+
+ } else 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;
+ usec_t k = (usec_t) z * table[i].usec;
+
+ for (; n > 0; n--)
+ k /= 10;
+
+ r += (usec_t) l * table[i].usec + k;
p = e + strlen(table[i].suffix);
+
+ something = true;
break;
}
if (i >= ELEMENTSOF(table))
return -EINVAL;
- } while (*p != 0);
+ }
*usec = r;
@@ -614,15 +647,25 @@ int parse_nsec(const char *t, nsec_t *nsec) {
const char *p;
nsec_t r = 0;
+ bool something = false;
assert(t);
assert(nsec);
p = t;
- do {
- long long l;
+ for (;;) {
+ long long l, z = 0;
char *e;
- unsigned i;
+ unsigned i, n = 0;
+
+ p += strspn(p, WHITESPACE);
+
+ if (*p == 0) {
+ if (!something)
+ return -EINVAL;
+
+ break;
+ }
errno = 0;
l = strtoll(p, &e, 10);
@@ -633,22 +676,45 @@ int parse_nsec(const char *t, nsec_t *nsec) {
if (l < 0)
return -ERANGE;
- if (e == p)
+ if (*e == '.') {
+ char *b = e + 1;
+
+ errno = 0;
+ z = strtoll(b, &e, 10);
+ if (errno > 0)
+ return -errno;
+
+ if (z < 0)
+ return -ERANGE;
+
+ if (e == b)
+ return -EINVAL;
+
+ n = e - b;
+
+ } else if (e == p)
return -EINVAL;
e += strspn(e, WHITESPACE);
for (i = 0; i < ELEMENTSOF(table); i++)
if (startswith(e, table[i].suffix)) {
- r += (nsec_t) l * table[i].nsec;
+ nsec_t k = (nsec_t) z * table[i].nsec;
+
+ for (; n > 0; n--)
+ k /= 10;
+
+ r += (nsec_t) l * table[i].nsec + k;
p = e + strlen(table[i].suffix);
+
+ something = true;
break;
}
if (i >= ELEMENTSOF(table))
return -EINVAL;
- } while (*p != 0);
+ }
*nsec = r;