1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include <sys/socket.h>
10 #include "alloc-util.h"
11 #include "errno-list.h"
12 #include "extract-word.h"
13 #include "locale-util.h"
15 #include "missing_network.h"
16 #include "parse-util.h"
17 #include "process-util.h"
18 #include "stat-util.h"
19 #include "string-util.h"
22 int parse_boolean(const char *v
) {
47 int parse_tristate_full(const char *v
, const char *third
, int *ret
) {
50 if (isempty(v
) || streq_ptr(v
, third
)) { /* Empty string is always taken as the third/invalid/auto state */
65 int parse_pid(const char *s
, pid_t
* ret_pid
) {
72 r
= safe_atolu(s
, &ul
);
78 if ((unsigned long) pid
!= ul
)
81 if (!pid_is_valid(pid
))
89 int parse_mode(const char *s
, mode_t
*ret
) {
95 r
= safe_atou_full(s
, 8 |
96 SAFE_ATO_REFUSE_PLUS_MINUS
, /* Leading '+' or even '-' char? that's just weird,
97 * refuse. User might have wanted to add mode flags or
98 * so, but this parser doesn't allow that, so let's
111 int parse_ifindex(const char *s
) {
116 r
= safe_atoi(s
, &ifi
);
125 int parse_mtu(int family
, const char *s
, uint32_t *ret
) {
129 r
= parse_size(s
, 1024, &u
);
138 m
= IPV4_MIN_MTU
; /* This is 68 */
141 m
= IPV6_MIN_MTU
; /* This is 1280 */
154 int parse_size(const char *t
, uint64_t base
, uint64_t *size
) {
156 /* Soo, sometimes we want to parse IEC binary suffixes, and
157 * sometimes SI decimal suffixes. This function can parse
158 * both. Which one is the right way depends on the
159 * context. Wikipedia suggests that SI is customary for
160 * hardware metrics and network speeds, while IEC is
161 * customary for most data sizes used by software and volatile
162 * (RAM) memory. Hence be careful which one you pick!
164 * In either case we use just K, M, G as suffix, and not Ki,
165 * Mi, Gi or so (as IEC would suggest). That's because that's
166 * frickin' ugly. But this means you really need to make sure
167 * to document which base you are parsing when you use this
172 unsigned long long factor
;
175 static const struct table iec
[] = {
176 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
177 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
178 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
179 { "G", 1024ULL*1024ULL*1024ULL },
180 { "M", 1024ULL*1024ULL },
186 static const struct table si
[] = {
187 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
188 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
189 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
190 { "G", 1000ULL*1000ULL*1000ULL },
191 { "M", 1000ULL*1000ULL },
197 const struct table
*table
;
199 unsigned long long r
= 0;
200 unsigned n_entries
, start_pos
= 0;
203 assert(IN_SET(base
, 1000, 1024));
208 n_entries
= ELEMENTSOF(si
);
211 n_entries
= ELEMENTSOF(iec
);
216 unsigned long long l
, tmp
;
221 p
+= strspn(p
, WHITESPACE
);
224 l
= strtoull(p
, &e
, 10);
235 /* strtoull() itself would accept space/+/- */
236 if (ascii_isdigit(*e
)) {
237 unsigned long long l2
;
240 l2
= strtoull(e
, &e2
, 10);
244 /* Ignore failure. E.g. 10.M is valid */
251 e
+= strspn(e
, WHITESPACE
);
253 for (i
= start_pos
; i
< n_entries
; i
++)
254 if (startswith(e
, table
[i
].suffix
))
260 if (l
+ (frac
> 0) > ULLONG_MAX
/ table
[i
].factor
)
263 tmp
= l
* table
[i
].factor
+ (unsigned long long) (frac
* table
[i
].factor
);
264 if (tmp
> ULLONG_MAX
- r
)
268 if ((unsigned long long) (uint64_t) r
!= r
)
271 p
= e
+ strlen(table
[i
].suffix
);
282 int parse_sector_size(const char *t
, uint64_t *ret
) {
290 r
= safe_atou64(t
, &ss
);
292 return log_error_errno(r
, "Failed to parse sector size parameter %s", t
);
293 if (ss
< 512 || ss
> 4096) /* Allow up to 4K due to dm-crypt support and 4K alignment by the homed LUKS backend */
294 return log_error_errno(SYNTHETIC_ERRNO(ERANGE
), "Sector size not between 512 and 4096: %s", t
);
296 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Sector size not power of 2: %s", t
);
302 int parse_range(const char *t
, unsigned *lower
, unsigned *upper
) {
303 _cleanup_free_
char *word
= NULL
;
310 /* Extract the lower bound. */
311 r
= extract_first_word(&t
, &word
, "-", EXTRACT_DONT_COALESCE_SEPARATORS
);
317 r
= safe_atou(word
, &l
);
321 /* Check for the upper bound and extract it if needed */
323 /* Single number with no dashes. */
326 /* Trailing dash is an error. */
329 r
= safe_atou(t
, &u
);
339 int parse_errno(const char *t
) {
344 r
= errno_from_name(t
);
348 r
= safe_atoi(t
, &e
);
352 /* 0 is also allowed here */
353 if (!errno_is_valid(e
) && e
!= 0)
359 int parse_fd(const char *t
) {
364 r
= safe_atoi(t
, &fd
);
374 static const char *mangle_base(const char *s
, unsigned *base
) {
380 /* Base already explicitly specified, then don't do anything. */
381 if (SAFE_ATO_MASK_FLAGS(*base
) != 0)
384 /* Support Python 3 style "0b" and 0x" prefixes, because they truly make sense, much more than C's "0" prefix for octal. */
385 k
= STARTSWITH_SET(s
, "0b", "0B");
387 *base
= 2 | (*base
& SAFE_ATO_ALL_FLAGS
);
391 k
= STARTSWITH_SET(s
, "0o", "0O");
393 *base
= 8 | (*base
& SAFE_ATO_ALL_FLAGS
);
400 int safe_atou_full(const char *s
, unsigned base
, unsigned *ret_u
) {
405 assert(SAFE_ATO_MASK_FLAGS(base
) <= 16);
407 /* strtoul() is happy to parse negative values, and silently converts them to unsigned values without
408 * generating an error. We want a clean error, hence let's look for the "-" prefix on our own, and
409 * generate an error. But let's do so only after strtoul() validated that the string is clean
410 * otherwise, so that we return EINVAL preferably over ERANGE. */
412 if (FLAGS_SET(base
, SAFE_ATO_REFUSE_LEADING_WHITESPACE
) &&
413 strchr(WHITESPACE
, s
[0]))
416 s
+= strspn(s
, WHITESPACE
);
418 if (FLAGS_SET(base
, SAFE_ATO_REFUSE_PLUS_MINUS
) &&
419 IN_SET(s
[0], '+', '-'))
420 return -EINVAL
; /* Note that we check the "-" prefix again a second time below, but return a
421 * different error. I.e. if the SAFE_ATO_REFUSE_PLUS_MINUS flag is set we
422 * blanket refuse +/- prefixed integers, while if it is missing we'll just
423 * return ERANGE, because the string actually parses correctly, but doesn't
424 * fit in the return type. */
426 if (FLAGS_SET(base
, SAFE_ATO_REFUSE_LEADING_ZERO
) &&
427 s
[0] == '0' && !streq(s
, "0"))
428 return -EINVAL
; /* This is particularly useful to avoid ambiguities between C's octal
429 * notation and assumed-to-be-decimal integers with a leading zero. */
431 s
= mangle_base(s
, &base
);
434 l
= strtoul(s
, &x
, SAFE_ATO_MASK_FLAGS(base
) /* Let's mask off the flags bits so that only the actual
438 if (!x
|| x
== s
|| *x
!= 0)
440 if (l
!= 0 && s
[0] == '-')
442 if ((unsigned long) (unsigned) l
!= l
)
446 *ret_u
= (unsigned) l
;
451 int safe_atou_bounded(const char *s
, unsigned min
, unsigned max
, unsigned *ret
) {
455 r
= safe_atou(s
, &v
);
459 if (v
< min
|| v
> max
)
466 int safe_atoi(const char *s
, int *ret_i
) {
473 s
+= strspn(s
, WHITESPACE
);
474 s
= mangle_base(s
, &base
);
477 l
= strtol(s
, &x
, base
);
480 if (!x
|| x
== s
|| *x
!= 0)
482 if ((long) (int) l
!= l
)
491 int safe_atollu_full(const char *s
, unsigned base
, unsigned long long *ret_llu
) {
493 unsigned long long l
;
496 assert(SAFE_ATO_MASK_FLAGS(base
) <= 16);
498 if (FLAGS_SET(base
, SAFE_ATO_REFUSE_LEADING_WHITESPACE
) &&
499 strchr(WHITESPACE
, s
[0]))
502 s
+= strspn(s
, WHITESPACE
);
504 if (FLAGS_SET(base
, SAFE_ATO_REFUSE_PLUS_MINUS
) &&
505 IN_SET(s
[0], '+', '-'))
508 if (FLAGS_SET(base
, SAFE_ATO_REFUSE_LEADING_ZERO
) &&
509 s
[0] == '0' && s
[1] != 0)
512 s
= mangle_base(s
, &base
);
515 l
= strtoull(s
, &x
, SAFE_ATO_MASK_FLAGS(base
));
518 if (!x
|| x
== s
|| *x
!= 0)
520 if (l
!= 0 && s
[0] == '-')
529 int safe_atolli(const char *s
, long long int *ret_lli
) {
536 s
+= strspn(s
, WHITESPACE
);
537 s
= mangle_base(s
, &base
);
540 l
= strtoll(s
, &x
, base
);
543 if (!x
|| x
== s
|| *x
!= 0)
552 int safe_atou8_full(const char *s
, unsigned base
, uint8_t *ret
) {
556 r
= safe_atou_full(s
, base
, &u
);
566 int safe_atou16_full(const char *s
, unsigned base
, uint16_t *ret
) {
570 r
= safe_atou_full(s
, base
, &u
);
580 int safe_atoi16(const char *s
, int16_t *ret
) {
587 s
+= strspn(s
, WHITESPACE
);
588 s
= mangle_base(s
, &base
);
591 l
= strtol(s
, &x
, base
);
594 if (!x
|| x
== s
|| *x
!= 0)
596 if ((long) (int16_t) l
!= l
)
605 int safe_atod(const char *s
, double *ret_d
) {
606 _cleanup_(freelocalep
) locale_t loc
= (locale_t
) 0;
612 loc
= newlocale(LC_NUMERIC_MASK
, "C", (locale_t
) 0);
613 if (loc
== (locale_t
) 0)
617 d
= strtod_l(s
, &x
, loc
);
620 if (!x
|| x
== s
|| *x
!= 0)
629 int parse_fractional_part_u(const char **p
, size_t digits
, unsigned *res
) {
635 /* accept any number of digits, strtoull is limited to 19 */
636 for (size_t i
= 0; i
< digits
; i
++, s
++) {
637 if (!ascii_isdigit(*s
)) {
641 /* too few digits, pad with 0 */
642 for (; i
< digits
; i
++)
653 if (*s
>= '5' && *s
<= '9')
656 s
+= strspn(s
, DIGITS
);
664 int parse_nice(const char *p
, int *ret
) {
667 r
= safe_atoi(p
, &n
);
671 if (!nice_is_valid(n
))
678 int parse_ip_port(const char *s
, uint16_t *ret
) {
682 r
= safe_atou16_full(s
, SAFE_ATO_REFUSE_LEADING_WHITESPACE
, &l
);
694 int parse_ip_port_range(const char *s
, uint16_t *low
, uint16_t *high
, bool allow_zero
) {
698 r
= parse_range(s
, &l
, &h
);
702 if (l
> 65535 || h
> 65535)
705 if (!allow_zero
&& (l
== 0 || h
== 0))
717 int parse_ip_prefix_length(const char *s
, int *ret
) {
721 r
= safe_atou(s
, &l
);
733 int parse_oom_score_adjust(const char *s
, int *ret
) {
739 r
= safe_atoi(s
, &v
);
743 if (!oom_score_adjust_is_valid(v
))
750 int store_loadavg_fixed_point(unsigned long i
, unsigned long f
, loadavg_t
*ret
) {
753 if (i
>= (~0UL << LOADAVG_PRECISION_BITS
))
756 i
= i
<< LOADAVG_PRECISION_BITS
;
757 f
= DIV_ROUND_UP((f
<< LOADAVG_PRECISION_BITS
), 100);
759 if (f
>= LOADAVG_FIXED_POINT_1_0
)
766 int parse_loadavg_fixed_point(const char *s
, loadavg_t
*ret
) {
767 const char *d
, *f_str
, *i_str
;
778 i_str
= strndupa_safe(s
, d
- s
);
781 r
= safe_atolu_full(i_str
, 10, &i
);
785 r
= safe_atolu_full(f_str
, 10, &f
);
789 return store_loadavg_fixed_point(i
, f
, ret
);
792 /* Limitations are described in https://www.netfilter.org/projects/nftables/manpage.html and
793 * https://bugzilla.netfilter.org/show_bug.cgi?id=1175 */
794 bool nft_identifier_valid(const char *id
) {
798 size_t len
= strlen(id
);
799 if (len
== 0 || len
> 31)
802 if (!ascii_isalpha(id
[0]))
805 for (size_t i
= 1; i
< len
; i
++)
806 if (!ascii_isalpha(id
[i
]) && !ascii_isdigit(id
[i
]) && !IN_SET(id
[i
], '/', '\\', '_', '.'))