1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
30 #include "alloc-util.h"
31 #include "extract-word.h"
33 #include "parse-util.h"
34 #include "string-util.h"
36 int parse_boolean(const char *v
) {
39 if (streq(v
, "1") || strcaseeq(v
, "yes") || strcaseeq(v
, "y") || strcaseeq(v
, "true") || strcaseeq(v
, "t") || strcaseeq(v
, "on"))
41 else if (streq(v
, "0") || strcaseeq(v
, "no") || strcaseeq(v
, "n") || strcaseeq(v
, "false") || strcaseeq(v
, "f") || strcaseeq(v
, "off"))
47 int parse_pid(const char *s
, pid_t
* ret_pid
) {
55 r
= safe_atolu(s
, &ul
);
61 if ((unsigned long) pid
!= ul
)
71 int parse_mode(const char *s
, mode_t
*ret
) {
78 s
+= strspn(s
, WHITESPACE
);
86 if (!x
|| x
== s
|| *x
)
88 if (l
< 0 || l
> 07777)
95 int parse_ifindex(const char *s
, int *ret
) {
98 r
= safe_atoi(s
, &ifi
);
108 int parse_size(const char *t
, uint64_t base
, uint64_t *size
) {
110 /* Soo, sometimes we want to parse IEC binary suffixes, and
111 * sometimes SI decimal suffixes. This function can parse
112 * both. Which one is the right way depends on the
113 * context. Wikipedia suggests that SI is customary for
114 * hardware metrics and network speeds, while IEC is
115 * customary for most data sizes used by software and volatile
116 * (RAM) memory. Hence be careful which one you pick!
118 * In either case we use just K, M, G as suffix, and not Ki,
119 * Mi, Gi or so (as IEC would suggest). That's because that's
120 * frickin' ugly. But this means you really need to make sure
121 * to document which base you are parsing when you use this
126 unsigned long long factor
;
129 static const struct table iec
[] = {
130 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
131 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
132 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
133 { "G", 1024ULL*1024ULL*1024ULL },
134 { "M", 1024ULL*1024ULL },
140 static const struct table si
[] = {
141 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
142 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
143 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
144 { "G", 1000ULL*1000ULL*1000ULL },
145 { "M", 1000ULL*1000ULL },
151 const struct table
*table
;
153 unsigned long long r
= 0;
154 unsigned n_entries
, start_pos
= 0;
157 assert(base
== 1000 || base
== 1024);
162 n_entries
= ELEMENTSOF(si
);
165 n_entries
= ELEMENTSOF(iec
);
170 unsigned long long l
, tmp
;
175 p
+= strspn(p
, WHITESPACE
);
178 l
= strtoull(p
, &e
, 10);
189 /* strtoull() itself would accept space/+/- */
190 if (*e
>= '0' && *e
<= '9') {
191 unsigned long long l2
;
194 l2
= strtoull(e
, &e2
, 10);
198 /* Ignore failure. E.g. 10.M is valid */
205 e
+= strspn(e
, WHITESPACE
);
207 for (i
= start_pos
; i
< n_entries
; i
++)
208 if (startswith(e
, table
[i
].suffix
))
214 if (l
+ (frac
> 0) > ULLONG_MAX
/ table
[i
].factor
)
217 tmp
= l
* table
[i
].factor
+ (unsigned long long) (frac
* table
[i
].factor
);
218 if (tmp
> ULLONG_MAX
- r
)
222 if ((unsigned long long) (uint64_t) r
!= r
)
225 p
= e
+ strlen(table
[i
].suffix
);
236 int parse_range(const char *t
, unsigned *lower
, unsigned *upper
) {
237 _cleanup_free_
char *word
= NULL
;
244 /* Extract the lower bound. */
245 r
= extract_first_word(&t
, &word
, "-", EXTRACT_DONT_COALESCE_SEPARATORS
);
251 r
= safe_atou(word
, &l
);
255 /* Check for the upper bound and extract it if needed */
257 /* Single number with no dashes. */
260 /* Trailing dash is an error. */
263 r
= safe_atou(t
, &u
);
273 char *format_bytes(char *buf
, size_t l
, uint64_t t
) {
276 /* This only does IEC units so far */
278 static const struct {
282 { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
283 { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
284 { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
285 { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
286 { "M", UINT64_C(1024)*UINT64_C(1024) },
287 { "K", UINT64_C(1024) },
290 if (t
== (uint64_t) -1)
293 for (i
= 0; i
< ELEMENTSOF(table
); i
++) {
295 if (t
>= table
[i
].factor
) {
297 "%" PRIu64
".%" PRIu64
"%s",
299 ((t
*UINT64_C(10)) / table
[i
].factor
) % UINT64_C(10),
306 snprintf(buf
, l
, "%" PRIu64
"B", t
);
314 int safe_atou(const char *s
, unsigned *ret_u
) {
321 /* strtoul() is happy to parse negative values, and silently
322 * converts them to unsigned values without generating an
323 * error. We want a clean error, hence let's look for the "-"
324 * prefix on our own, and generate an error. But let's do so
325 * only after strtoul() validated that the string is clean
326 * otherwise, so that we return EINVAL preferably over
329 s
+= strspn(s
, WHITESPACE
);
332 l
= strtoul(s
, &x
, 0);
335 if (!x
|| x
== s
|| *x
)
339 if ((unsigned long) (unsigned) l
!= l
)
342 *ret_u
= (unsigned) l
;
346 int safe_atoi(const char *s
, int *ret_i
) {
354 l
= strtol(s
, &x
, 0);
357 if (!x
|| x
== s
|| *x
)
359 if ((long) (int) l
!= l
)
366 int safe_atollu(const char *s
, long long unsigned *ret_llu
) {
368 unsigned long long l
;
373 s
+= strspn(s
, WHITESPACE
);
376 l
= strtoull(s
, &x
, 0);
379 if (!x
|| x
== s
|| *x
)
388 int safe_atolli(const char *s
, long long int *ret_lli
) {
396 l
= strtoll(s
, &x
, 0);
399 if (!x
|| x
== s
|| *x
)
406 int safe_atou8(const char *s
, uint8_t *ret
) {
413 s
+= strspn(s
, WHITESPACE
);
416 l
= strtoul(s
, &x
, 0);
419 if (!x
|| x
== s
|| *x
)
423 if ((unsigned long) (uint8_t) l
!= l
)
430 int safe_atou16(const char *s
, uint16_t *ret
) {
437 s
+= strspn(s
, WHITESPACE
);
440 l
= strtoul(s
, &x
, 0);
443 if (!x
|| x
== s
|| *x
)
447 if ((unsigned long) (uint16_t) l
!= l
)
454 int safe_atoi16(const char *s
, int16_t *ret
) {
462 l
= strtol(s
, &x
, 0);
465 if (!x
|| x
== s
|| *x
)
467 if ((long) (int16_t) l
!= l
)
474 int safe_atod(const char *s
, double *ret_d
) {
482 loc
= newlocale(LC_NUMERIC_MASK
, "C", (locale_t
) 0);
483 if (loc
== (locale_t
) 0)
487 d
= strtod_l(s
, &x
, loc
);
492 if (!x
|| x
== s
|| *x
) {
502 int parse_fractional_part_u(const char **p
, size_t digits
, unsigned *res
) {
509 /* accept any number of digits, strtoull is limted to 19 */
510 for(i
=0; i
< digits
; i
++,s
++) {
511 if (*s
< '0' || *s
> '9') {
515 /* too few digits, pad with 0 */
516 for (; i
< digits
; i
++)
527 if (*s
>= '5' && *s
<= '9')
530 s
+= strspn(s
, DIGITS
);