1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "alloc-util.h"
29 #include "errno-list.h"
30 //#include "extract-word.h"
31 //#include "locale-util.h"
33 #include "parse-util.h"
34 #include "process-util.h"
35 #include "string-util.h"
37 /// Additional includes needed by elogind
38 #include "musl_missing.h"
40 int parse_boolean(const char *v) {
43 if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
45 else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
51 int parse_pid(const char *s, pid_t* ret_pid) {
59 r = safe_atolu(s, &ul);
65 if ((unsigned long) pid != ul)
68 if (!pid_is_valid(pid))
75 int parse_mode(const char *s, mode_t *ret) {
82 s += strspn(s, WHITESPACE);
90 if (!x || x == s || *x != 0)
92 if (l < 0 || l > 07777)
99 int parse_ifindex(const char *s, int *ret) {
102 r = safe_atoi(s, &ifi);
112 int parse_size(const char *t, uint64_t base, uint64_t *size) {
114 /* Soo, sometimes we want to parse IEC binary suffixes, and
115 * sometimes SI decimal suffixes. This function can parse
116 * both. Which one is the right way depends on the
117 * context. Wikipedia suggests that SI is customary for
118 * hardware metrics and network speeds, while IEC is
119 * customary for most data sizes used by software and volatile
120 * (RAM) memory. Hence be careful which one you pick!
122 * In either case we use just K, M, G as suffix, and not Ki,
123 * Mi, Gi or so (as IEC would suggest). That's because that's
124 * frickin' ugly. But this means you really need to make sure
125 * to document which base you are parsing when you use this
130 unsigned long long factor;
133 static const struct table iec[] = {
134 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
135 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
136 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
137 { "G", 1024ULL*1024ULL*1024ULL },
138 { "M", 1024ULL*1024ULL },
144 static const struct table si[] = {
145 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
146 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
147 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
148 { "G", 1000ULL*1000ULL*1000ULL },
149 { "M", 1000ULL*1000ULL },
155 const struct table *table;
157 unsigned long long r = 0;
158 unsigned n_entries, start_pos = 0;
161 assert(IN_SET(base, 1000, 1024));
166 n_entries = ELEMENTSOF(si);
169 n_entries = ELEMENTSOF(iec);
174 unsigned long long l, tmp;
179 p += strspn(p, WHITESPACE);
182 l = strtoull(p, &e, 10);
193 /* strtoull() itself would accept space/+/- */
194 if (*e >= '0' && *e <= '9') {
195 unsigned long long l2;
198 l2 = strtoull(e, &e2, 10);
202 /* Ignore failure. E.g. 10.M is valid */
209 e += strspn(e, WHITESPACE);
211 for (i = start_pos; i < n_entries; i++)
212 if (startswith(e, table[i].suffix))
218 if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
221 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
222 if (tmp > ULLONG_MAX - r)
226 if ((unsigned long long) (uint64_t) r != r)
229 p = e + strlen(table[i].suffix);
240 #if 0 /// UNNEEDED by elogind
241 int parse_range(const char *t, unsigned *lower, unsigned *upper) {
242 _cleanup_free_ char *word = NULL;
249 /* Extract the lower bound. */
250 r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
256 r = safe_atou(word, &l);
260 /* Check for the upper bound and extract it if needed */
262 /* Single number with no dashes. */
265 /* Trailing dash is an error. */
268 r = safe_atou(t, &u);
279 int parse_errno(const char *t) {
284 r = errno_from_name(t);
288 r = safe_atoi(t, &e);
292 /* 0 is also allowed here */
293 if (!errno_is_valid(e) && e != 0)
299 int parse_syscall_and_errno(const char *in, char **name, int *error) {
300 _cleanup_free_ char *n = NULL;
309 * This parse "syscall:errno" like "uname:EILSEQ", "@sync:255".
310 * If errno is omitted, then error is set to -1.
311 * Empty syscall name is not allowed.
312 * Here, we do not check that the syscall name is valid or not.
317 e = parse_errno(p + 1);
321 n = strndup(in, p - in);
338 char *format_bytes(char *buf, size_t l, uint64_t t) {
341 /* This only does IEC units so far */
343 static const struct {
347 { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
348 { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
349 { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
350 { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
351 { "M", UINT64_C(1024)*UINT64_C(1024) },
352 { "K", UINT64_C(1024) },
355 if (t == (uint64_t) -1)
358 for (i = 0; i < ELEMENTSOF(table); i++) {
360 if (t >= table[i].factor) {
362 "%" PRIu64 ".%" PRIu64 "%s",
364 ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
371 snprintf(buf, l, "%" PRIu64 "B", t);
379 int safe_atou(const char *s, unsigned *ret_u) {
386 /* strtoul() is happy to parse negative values, and silently
387 * converts them to unsigned values without generating an
388 * error. We want a clean error, hence let's look for the "-"
389 * prefix on our own, and generate an error. But let's do so
390 * only after strtoul() validated that the string is clean
391 * otherwise, so that we return EINVAL preferably over
394 s += strspn(s, WHITESPACE);
397 l = strtoul(s, &x, 0);
400 if (!x || x == s || *x != 0)
404 if ((unsigned long) (unsigned) l != l)
407 *ret_u = (unsigned) l;
411 int safe_atoi(const char *s, int *ret_i) {
419 l = strtol(s, &x, 0);
422 if (!x || x == s || *x != 0)
424 if ((long) (int) l != l)
431 int safe_atollu(const char *s, long long unsigned *ret_llu) {
433 unsigned long long l;
438 s += strspn(s, WHITESPACE);
441 l = strtoull(s, &x, 0);
444 if (!x || x == s || *x != 0)
453 int safe_atolli(const char *s, long long int *ret_lli) {
461 l = strtoll(s, &x, 0);
464 if (!x || x == s || *x != 0)
471 int safe_atou8(const char *s, uint8_t *ret) {
478 s += strspn(s, WHITESPACE);
481 l = strtoul(s, &x, 0);
484 if (!x || x == s || *x != 0)
488 if ((unsigned long) (uint8_t) l != l)
495 int safe_atou16(const char *s, uint16_t *ret) {
502 s += strspn(s, WHITESPACE);
505 l = strtoul(s, &x, 0);
508 if (!x || x == s || *x != 0)
512 if ((unsigned long) (uint16_t) l != l)
519 int safe_atoi16(const char *s, int16_t *ret) {
527 l = strtol(s, &x, 0);
530 if (!x || x == s || *x != 0)
532 if ((long) (int16_t) l != l)
539 int safe_atoux16(const char *s, uint16_t *ret) {
546 s += strspn(s, WHITESPACE);
549 l = strtoul(s, &x, 16);
552 if (!x || x == s || *x != 0)
556 if ((unsigned long) (uint16_t) l != l)
563 int safe_atod(const char *s, double *ret_d) {
564 _cleanup_(freelocalep) locale_t loc = (locale_t) 0;
571 loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
572 if (loc == (locale_t) 0)
576 d = strtod_l(s, &x, loc);
579 if (!x || x == s || *x != 0)
586 int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
593 /* accept any number of digits, strtoull is limted to 19 */
594 for (i=0; i < digits; i++,s++) {
595 if (*s < '0' || *s > '9') {
599 /* too few digits, pad with 0 */
600 for (; i < digits; i++)
611 if (*s >= '5' && *s <= '9')
614 s += strspn(s, DIGITS);
622 int parse_percent_unbounded(const char *p) {
626 pc = endswith(p, "%");
630 n = strndupa(p, pc - p);
631 r = safe_atoi(n, &v);
640 int parse_percent(const char *p) {
643 v = parse_percent_unbounded(p);
650 #if 0 /// UNNEEDED by elogind
651 int parse_nice(const char *p, int *ret) {
654 r = safe_atoi(p, &n);
658 if (!nice_is_valid(n))
665 int parse_ip_port(const char *s, uint16_t *ret) {
669 r = safe_atou16(s, &l);
682 int parse_dev(const char *s, dev_t *ret) {
686 if (sscanf(s, "%u:%u", &x, &y) != 2)
690 if ((unsigned) major(d) != x || (unsigned) minor(d) != y)