#include <unistd.h>
#include "alloc-util.h"
-#include "def.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "io-util.h"
#include "log.h"
#include "macro.h"
+#include "missing_timerfd.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
-#include "serialize.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
return tmp.return_value;
}
-static char* extract_multiplier(char *p, usec_t *multiplier) {
+static const char* extract_multiplier(const char *p, usec_t *multiplier) {
static const struct {
const char *suffix;
usec_t usec;
for (;;) {
usec_t multiplier = default_unit, k;
- long long l, z = 0;
- unsigned n = 0;
+ long long l;
char *e;
p += strspn(p, WHITESPACE);
return -ERANGE;
if (*e == '.') {
- char *b = e + 1;
-
- /* Don't allow "0.-0", "3.+1" or "3. 1" */
- if (IN_SET(*b, '-', '+') || isspace(*b))
- return -EINVAL;
-
- 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;
-
+ p = e + 1;
+ p += strspn(p, DIGITS);
} else if (e == p)
return -EINVAL;
+ else
+ p = e;
- e += strspn(e, WHITESPACE);
- p = extract_multiplier(e, &multiplier);
+ s = extract_multiplier(p + strspn(p, WHITESPACE), &multiplier);
+ if (s == p && *s != '\0')
+ /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56'*/
+ return -EINVAL;
- something = true;
+ p = s;
+ if ((usec_t) l >= USEC_INFINITY / multiplier)
+ return -ERANGE;
- k = ((usec_t) -1) / multiplier;
- if ((usec_t) l + 1 >= k || (usec_t) z >= k)
+ k = (usec_t) l * multiplier;
+ if (k >= USEC_INFINITY - r)
return -ERANGE;
- k = (usec_t) z * multiplier;
+ r += k;
- for (; n > 0; n--)
- k /= 10;
+ something = true;
- k += (usec_t) l * multiplier;
- if (k >= ((usec_t) -1) - r)
- return -ERANGE;
+ if (*e == '.') {
+ usec_t m = multiplier / 10;
+ const char *b;
- r += k;
+ for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) {
+ k = (usec_t) (*b - '0') * m;
+ if (k >= USEC_INFINITY - r)
+ return -ERANGE;
+
+ r += k;
+ }
+
+ /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge"*/
+ if (b == e + 1)
+ return -EINVAL;
+ }
}
*usec = r;
return r;
}
-int parse_nsec(const char *t, nsec_t *nsec) {
+int parse_sec_def_infinity(const char *t, usec_t *ret) {
+ t += strspn(t, WHITESPACE);
+ if (isempty(t)) {
+ *ret = USEC_INFINITY;
+ return 0;
+ }
+ return parse_sec(t, ret);
+}
+
+static const char* extract_nsec_multiplier(const char *p, nsec_t *multiplier) {
static const struct {
const char *suffix;
nsec_t nsec;
} table[] = {
- { "seconds", NSEC_PER_SEC },
- { "second", NSEC_PER_SEC },
- { "sec", NSEC_PER_SEC },
- { "s", NSEC_PER_SEC },
+ { "seconds", NSEC_PER_SEC },
+ { "second", NSEC_PER_SEC },
+ { "sec", NSEC_PER_SEC },
+ { "s", NSEC_PER_SEC },
{ "minutes", NSEC_PER_MINUTE },
- { "minute", NSEC_PER_MINUTE },
- { "min", NSEC_PER_MINUTE },
- { "months", NSEC_PER_MONTH },
- { "month", NSEC_PER_MONTH },
- { "msec", NSEC_PER_MSEC },
- { "ms", NSEC_PER_MSEC },
- { "m", NSEC_PER_MINUTE },
- { "hours", NSEC_PER_HOUR },
- { "hour", NSEC_PER_HOUR },
- { "hr", NSEC_PER_HOUR },
- { "h", NSEC_PER_HOUR },
- { "days", NSEC_PER_DAY },
- { "day", NSEC_PER_DAY },
- { "d", NSEC_PER_DAY },
- { "weeks", NSEC_PER_WEEK },
- { "week", NSEC_PER_WEEK },
- { "w", NSEC_PER_WEEK },
- { "years", NSEC_PER_YEAR },
- { "year", NSEC_PER_YEAR },
- { "y", NSEC_PER_YEAR },
- { "usec", NSEC_PER_USEC },
- { "us", NSEC_PER_USEC },
- { "µs", NSEC_PER_USEC },
- { "nsec", 1ULL },
- { "ns", 1ULL },
- { "", 1ULL }, /* default is nsec */
+ { "minute", NSEC_PER_MINUTE },
+ { "min", NSEC_PER_MINUTE },
+ { "months", NSEC_PER_MONTH },
+ { "month", NSEC_PER_MONTH },
+ { "M", NSEC_PER_MONTH },
+ { "msec", NSEC_PER_MSEC },
+ { "ms", NSEC_PER_MSEC },
+ { "m", NSEC_PER_MINUTE },
+ { "hours", NSEC_PER_HOUR },
+ { "hour", NSEC_PER_HOUR },
+ { "hr", NSEC_PER_HOUR },
+ { "h", NSEC_PER_HOUR },
+ { "days", NSEC_PER_DAY },
+ { "day", NSEC_PER_DAY },
+ { "d", NSEC_PER_DAY },
+ { "weeks", NSEC_PER_WEEK },
+ { "week", NSEC_PER_WEEK },
+ { "w", NSEC_PER_WEEK },
+ { "years", NSEC_PER_YEAR },
+ { "year", NSEC_PER_YEAR },
+ { "y", NSEC_PER_YEAR },
+ { "usec", NSEC_PER_USEC },
+ { "us", NSEC_PER_USEC },
+ { "µs", NSEC_PER_USEC },
+ { "nsec", 1ULL },
+ { "ns", 1ULL },
+ { "", 1ULL }, /* default is nsec */
};
+ size_t i;
+
+ for (i = 0; i < ELEMENTSOF(table); i++) {
+ char *e;
+ e = startswith(p, table[i].suffix);
+ if (e) {
+ *multiplier = table[i].nsec;
+ return e;
+ }
+ }
+
+ return p;
+}
+
+int parse_nsec(const char *t, nsec_t *nsec) {
const char *p, *s;
nsec_t r = 0;
bool something = false;
}
for (;;) {
- long long l, z = 0;
- size_t n = 0, i;
+ nsec_t multiplier = 1, k;
+ long long l;
char *e;
p += strspn(p, WHITESPACE);
break;
}
- if (*p == '-')
+ if (*p == '-') /* Don't allow "-0" */
return -ERANGE;
errno = 0;
return -ERANGE;
if (*e == '.') {
- char *b = e + 1;
-
- if (IN_SET(*b, '-', '+') || isspace(*b))
- return -EINVAL;
-
- 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;
-
+ p = e + 1;
+ p += strspn(p, DIGITS);
} else if (e == p)
return -EINVAL;
+ else
+ p = e;
- e += strspn(e, WHITESPACE);
+ s = extract_nsec_multiplier(p + strspn(p, WHITESPACE), &multiplier);
+ if (s == p && *s != '\0')
+ /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56'*/
+ return -EINVAL;
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- nsec_t k;
+ p = s;
- k = ((nsec_t) -1) / table[i].nsec;
- if ((nsec_t) l + 1 >= k || (nsec_t) z >= k)
- return -ERANGE;
+ if ((nsec_t) l >= NSEC_INFINITY / multiplier)
+ return -ERANGE;
+
+ k = (nsec_t) l * multiplier;
+ if (k >= NSEC_INFINITY - r)
+ return -ERANGE;
- k = (nsec_t) z * table[i].nsec;
+ r += k;
+
+ something = true;
- for (; n > 0; n--)
- k /= 10;
+ if (*e == '.') {
+ nsec_t m = multiplier / 10;
+ const char *b;
- k += (nsec_t) l * table[i].nsec;
- if (k >= ((nsec_t) -1) - r)
+ for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) {
+ k = (nsec_t) (*b - '0') * m;
+ if (k >= NSEC_INFINITY - r)
return -ERANGE;
r += k;
- p = e + strlen(table[i].suffix);
-
- something = true;
- break;
}
- if (i >= ELEMENTSOF(table))
- return -EINVAL;
-
+ /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge"*/
+ if (b == e + 1)
+ return -EINVAL;
+ }
}
*nsec = r;
if (r < 0)
return r; /* returns EINVAL if not a symlink */
- e = path_startswith(t, "/usr/share/zoneinfo/");
- if (!e)
- e = path_startswith(t, "../usr/share/zoneinfo/");
+ e = PATH_STARTSWITH_SET(t, "/usr/share/zoneinfo/", "../usr/share/zoneinfo/");
if (!e)
return -EINVAL;