]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/parse-util.c
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/>.
22 #include "parse-util.h"
23 #include "string-util.h"
26 int parse_boolean(const char *v
) {
29 if (streq(v
, "1") || strcaseeq(v
, "yes") || strcaseeq(v
, "y") || strcaseeq(v
, "true") || strcaseeq(v
, "t") || strcaseeq(v
, "on"))
31 else if (streq(v
, "0") || strcaseeq(v
, "no") || strcaseeq(v
, "n") || strcaseeq(v
, "false") || strcaseeq(v
, "f") || strcaseeq(v
, "off"))
37 int parse_pid(const char *s
, pid_t
* ret_pid
) {
45 r
= safe_atolu(s
, &ul
);
51 if ((unsigned long) pid
!= ul
)
61 int parse_mode(const char *s
, mode_t
*ret
) {
73 if (!x
|| x
== s
|| *x
)
75 if (l
< 0 || l
> 07777)
82 int parse_size(const char *t
, uint64_t base
, uint64_t *size
) {
84 /* Soo, sometimes we want to parse IEC binary suffixes, and
85 * sometimes SI decimal suffixes. This function can parse
86 * both. Which one is the right way depends on the
87 * context. Wikipedia suggests that SI is customary for
88 * hardware metrics and network speeds, while IEC is
89 * customary for most data sizes used by software and volatile
90 * (RAM) memory. Hence be careful which one you pick!
92 * In either case we use just K, M, G as suffix, and not Ki,
93 * Mi, Gi or so (as IEC would suggest). That's because that's
94 * frickin' ugly. But this means you really need to make sure
95 * to document which base you are parsing when you use this
100 unsigned long long factor
;
103 static const struct table iec
[] = {
104 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
105 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
106 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
107 { "G", 1024ULL*1024ULL*1024ULL },
108 { "M", 1024ULL*1024ULL },
114 static const struct table si
[] = {
115 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
116 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
117 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
118 { "G", 1000ULL*1000ULL*1000ULL },
119 { "M", 1000ULL*1000ULL },
125 const struct table
*table
;
127 unsigned long long r
= 0;
128 unsigned n_entries
, start_pos
= 0;
131 assert(base
== 1000 || base
== 1024);
136 n_entries
= ELEMENTSOF(si
);
139 n_entries
= ELEMENTSOF(iec
);
144 unsigned long long l
, tmp
;
149 p
+= strspn(p
, WHITESPACE
);
154 l
= strtoull(p
, &e
, 10);
163 /* strtoull() itself would accept space/+/- */
164 if (*e
>= '0' && *e
<= '9') {
165 unsigned long long l2
;
168 l2
= strtoull(e
, &e2
, 10);
172 /* Ignore failure. E.g. 10.M is valid */
179 e
+= strspn(e
, WHITESPACE
);
181 for (i
= start_pos
; i
< n_entries
; i
++)
182 if (startswith(e
, table
[i
].suffix
))
188 if (l
+ (frac
> 0) > ULLONG_MAX
/ table
[i
].factor
)
191 tmp
= l
* table
[i
].factor
+ (unsigned long long) (frac
* table
[i
].factor
);
192 if (tmp
> ULLONG_MAX
- r
)
196 if ((unsigned long long) (uint64_t) r
!= r
)
199 p
= e
+ strlen(table
[i
].suffix
);
210 char *format_bytes(char *buf
, size_t l
, uint64_t t
) {
213 /* This only does IEC units so far */
215 static const struct {
219 { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
220 { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
221 { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
222 { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
223 { "M", UINT64_C(1024)*UINT64_C(1024) },
224 { "K", UINT64_C(1024) },
227 if (t
== (uint64_t) -1)
230 for (i
= 0; i
< ELEMENTSOF(table
); i
++) {
232 if (t
>= table
[i
].factor
) {
234 "%" PRIu64
".%" PRIu64
"%s",
236 ((t
*UINT64_C(10)) / table
[i
].factor
) % UINT64_C(10),
243 snprintf(buf
, l
, "%" PRIu64
"B", t
);
251 int safe_atou(const char *s
, unsigned *ret_u
) {
259 l
= strtoul(s
, &x
, 0);
261 if (!x
|| x
== s
|| *x
|| errno
)
262 return errno
> 0 ? -errno
: -EINVAL
;
264 if ((unsigned long) (unsigned) l
!= l
)
267 *ret_u
= (unsigned) l
;
271 int safe_atoi(const char *s
, int *ret_i
) {
279 l
= strtol(s
, &x
, 0);
281 if (!x
|| x
== s
|| *x
|| errno
)
282 return errno
> 0 ? -errno
: -EINVAL
;
284 if ((long) (int) l
!= l
)
291 int safe_atollu(const char *s
, long long unsigned *ret_llu
) {
293 unsigned long long l
;
299 l
= strtoull(s
, &x
, 0);
301 if (!x
|| x
== s
|| *x
|| errno
)
302 return errno
? -errno
: -EINVAL
;
308 int safe_atolli(const char *s
, long long int *ret_lli
) {
316 l
= strtoll(s
, &x
, 0);
318 if (!x
|| x
== s
|| *x
|| errno
)
319 return errno
? -errno
: -EINVAL
;
325 int safe_atou8(const char *s
, uint8_t *ret
) {
333 l
= strtoul(s
, &x
, 0);
335 if (!x
|| x
== s
|| *x
|| errno
)
336 return errno
> 0 ? -errno
: -EINVAL
;
338 if ((unsigned long) (uint8_t) l
!= l
)
345 int safe_atou16(const char *s
, uint16_t *ret
) {
353 l
= strtoul(s
, &x
, 0);
355 if (!x
|| x
== s
|| *x
|| errno
)
356 return errno
> 0 ? -errno
: -EINVAL
;
358 if ((unsigned long) (uint16_t) l
!= l
)
365 int safe_atoi16(const char *s
, int16_t *ret
) {
373 l
= strtol(s
, &x
, 0);
375 if (!x
|| x
== s
|| *x
|| errno
)
376 return errno
> 0 ? -errno
: -EINVAL
;
378 if ((long) (int16_t) l
!= l
)
385 int safe_atod(const char *s
, double *ret_d
) {
393 loc
= newlocale(LC_NUMERIC_MASK
, "C", (locale_t
) 0);
394 if (loc
== (locale_t
) 0)
398 d
= strtod_l(s
, &x
, loc
);
400 if (!x
|| x
== s
|| *x
|| errno
) {
402 return errno
? -errno
: -EINVAL
;