Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <inttypes.h>
5 : : #include <linux/oom.h>
6 : : #include <locale.h>
7 : : #include <net/if.h>
8 : : #include <stdio.h>
9 : : #include <stdlib.h>
10 : : #include <string.h>
11 : : #include <sys/socket.h>
12 : :
13 : : #include "alloc-util.h"
14 : : #include "errno-list.h"
15 : : #include "extract-word.h"
16 : : #include "locale-util.h"
17 : : #include "macro.h"
18 : : #include "missing.h"
19 : : #include "parse-util.h"
20 : : #include "process-util.h"
21 : : #include "stat-util.h"
22 : : #include "string-util.h"
23 : :
24 : 904 : int parse_boolean(const char *v) {
25 [ - + ]: 904 : if (!v)
26 : 0 : return -EINVAL;
27 : :
28 [ + + + + : 904 : if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
+ + + + +
+ + + ]
29 : 264 : return 1;
30 [ + + + + : 640 : else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
+ + + + +
+ + + ]
31 : 312 : return 0;
32 : :
33 : 328 : return -EINVAL;
34 : : }
35 : :
36 : 1179 : int parse_pid(const char *s, pid_t* ret_pid) {
37 : 1179 : unsigned long ul = 0;
38 : : pid_t pid;
39 : : int r;
40 : :
41 [ - + ]: 1179 : assert(s);
42 [ - + ]: 1179 : assert(ret_pid);
43 : :
44 : 1179 : r = safe_atolu(s, &ul);
45 [ + + ]: 1179 : if (r < 0)
46 : 60 : return r;
47 : :
48 : 1119 : pid = (pid_t) ul;
49 : :
50 [ - + ]: 1119 : if ((unsigned long) pid != ul)
51 : 0 : return -ERANGE;
52 : :
53 [ + + ]: 1119 : if (!pid_is_valid(pid))
54 : 4 : return -ERANGE;
55 : :
56 : 1115 : *ret_pid = pid;
57 : 1115 : return 0;
58 : : }
59 : :
60 : 64 : int parse_mode(const char *s, mode_t *ret) {
61 : : char *x;
62 : : long l;
63 : :
64 [ - + ]: 64 : assert(s);
65 [ - + ]: 64 : assert(ret);
66 : :
67 : 64 : s += strspn(s, WHITESPACE);
68 [ + + ]: 64 : if (s[0] == '-')
69 : 8 : return -ERANGE;
70 : :
71 : 56 : errno = 0;
72 : 56 : l = strtol(s, &x, 8);
73 [ - + ]: 56 : if (errno > 0)
74 : 0 : return -errno;
75 [ + - + + : 56 : if (!x || x == s || *x != 0)
+ + ]
76 : 24 : return -EINVAL;
77 [ + - + + ]: 32 : if (l < 0 || l > 07777)
78 : 4 : return -ERANGE;
79 : :
80 : 28 : *ret = (mode_t) l;
81 : 28 : return 0;
82 : : }
83 : :
84 : 844 : int parse_ifindex(const char *s, int *ret) {
85 : : int ifi, r;
86 : :
87 [ - + ]: 844 : assert(s);
88 [ - + ]: 844 : assert(ret);
89 : :
90 : 844 : r = safe_atoi(s, &ifi);
91 [ + + ]: 844 : if (r < 0)
92 : 8 : return r;
93 [ - + ]: 836 : if (ifi <= 0)
94 : 0 : return -EINVAL;
95 : :
96 : 836 : *ret = ifi;
97 : 836 : return 0;
98 : : }
99 : :
100 : 0 : int parse_ifindex_or_ifname(const char *s, int *ret) {
101 : : int r;
102 : :
103 [ # # ]: 0 : assert(s);
104 [ # # ]: 0 : assert(ret);
105 : :
106 : 0 : r = parse_ifindex(s, ret);
107 [ # # ]: 0 : if (r >= 0)
108 : 0 : return r;
109 : :
110 : 0 : r = (int) if_nametoindex(s);
111 [ # # ]: 0 : if (r <= 0)
112 : 0 : return -errno;
113 : :
114 : 0 : *ret = r;
115 : 0 : return 0;
116 : : }
117 : :
118 : 112 : int parse_mtu(int family, const char *s, uint32_t *ret) {
119 : : uint64_t u;
120 : : size_t m;
121 : : int r;
122 : :
123 : 112 : r = parse_size(s, 1024, &u);
124 [ + + ]: 112 : if (r < 0)
125 : 28 : return r;
126 : :
127 [ + + ]: 84 : if (u > UINT32_MAX)
128 : 8 : return -ERANGE;
129 : :
130 [ + + ]: 76 : if (family == AF_INET6)
131 : 12 : m = IPV6_MIN_MTU; /* This is 1280 */
132 : : else
133 : 64 : m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */
134 : :
135 [ + + ]: 76 : if (u < m)
136 : 16 : return -ERANGE;
137 : :
138 : 60 : *ret = (uint32_t) u;
139 : 60 : return 0;
140 : : }
141 : :
142 : 352 : int parse_size(const char *t, uint64_t base, uint64_t *size) {
143 : :
144 : : /* Soo, sometimes we want to parse IEC binary suffixes, and
145 : : * sometimes SI decimal suffixes. This function can parse
146 : : * both. Which one is the right way depends on the
147 : : * context. Wikipedia suggests that SI is customary for
148 : : * hardware metrics and network speeds, while IEC is
149 : : * customary for most data sizes used by software and volatile
150 : : * (RAM) memory. Hence be careful which one you pick!
151 : : *
152 : : * In either case we use just K, M, G as suffix, and not Ki,
153 : : * Mi, Gi or so (as IEC would suggest). That's because that's
154 : : * frickin' ugly. But this means you really need to make sure
155 : : * to document which base you are parsing when you use this
156 : : * call. */
157 : :
158 : : struct table {
159 : : const char *suffix;
160 : : unsigned long long factor;
161 : : };
162 : :
163 : : static const struct table iec[] = {
164 : : { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
165 : : { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
166 : : { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
167 : : { "G", 1024ULL*1024ULL*1024ULL },
168 : : { "M", 1024ULL*1024ULL },
169 : : { "K", 1024ULL },
170 : : { "B", 1ULL },
171 : : { "", 1ULL },
172 : : };
173 : :
174 : : static const struct table si[] = {
175 : : { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
176 : : { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
177 : : { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
178 : : { "G", 1000ULL*1000ULL*1000ULL },
179 : : { "M", 1000ULL*1000ULL },
180 : : { "K", 1000ULL },
181 : : { "B", 1ULL },
182 : : { "", 1ULL },
183 : : };
184 : :
185 : : const struct table *table;
186 : : const char *p;
187 : 352 : unsigned long long r = 0;
188 : 352 : unsigned n_entries, start_pos = 0;
189 : :
190 [ - + ]: 352 : assert(t);
191 [ + - - + ]: 352 : assert(IN_SET(base, 1000, 1024));
192 [ - + ]: 352 : assert(size);
193 : :
194 [ + + ]: 352 : if (base == 1000) {
195 : 36 : table = si;
196 : 36 : n_entries = ELEMENTSOF(si);
197 : : } else {
198 : 316 : table = iec;
199 : 316 : n_entries = ELEMENTSOF(iec);
200 : : }
201 : :
202 : 352 : p = t;
203 : : do {
204 : : unsigned long long l, tmp;
205 : 448 : double frac = 0;
206 : : char *e;
207 : : unsigned i;
208 : :
209 : 448 : p += strspn(p, WHITESPACE);
210 : :
211 : 448 : errno = 0;
212 : 448 : l = strtoull(p, &e, 10);
213 [ + + ]: 448 : if (errno > 0)
214 : 112 : return -errno;
215 [ + + ]: 440 : if (e == p)
216 : 68 : return -EINVAL;
217 [ + + ]: 372 : if (*p == '-')
218 : 28 : return -ERANGE;
219 : :
220 [ + + ]: 344 : if (*e == '.') {
221 : 76 : e++;
222 : :
223 : : /* strtoull() itself would accept space/+/- */
224 [ + + + - ]: 76 : if (*e >= '0' && *e <= '9') {
225 : : unsigned long long l2;
226 : : char *e2;
227 : :
228 : 68 : l2 = strtoull(e, &e2, 10);
229 [ - + ]: 68 : if (errno > 0)
230 : 0 : return -errno;
231 : :
232 : : /* Ignore failure. E.g. 10.M is valid */
233 : 68 : frac = l2;
234 [ + + ]: 160 : for (; e < e2; e++)
235 : 92 : frac /= 10;
236 : : }
237 : : }
238 : :
239 : 344 : e += strspn(e, WHITESPACE);
240 : :
241 [ + + ]: 2056 : for (i = start_pos; i < n_entries; i++)
242 [ + + ]: 2052 : if (startswith(e, table[i].suffix))
243 : 340 : break;
244 : :
245 [ + + ]: 344 : if (i >= n_entries)
246 : 4 : return -EINVAL;
247 : :
248 [ + + ]: 340 : if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
249 : 4 : return -ERANGE;
250 : :
251 : 336 : tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
252 [ - + ]: 336 : if (tmp > ULLONG_MAX - r)
253 : 0 : return -ERANGE;
254 : :
255 : 336 : r += tmp;
256 : : if ((unsigned long long) (uint64_t) r != r)
257 : : return -ERANGE;
258 : :
259 : 336 : p = e + strlen(table[i].suffix);
260 : :
261 : 336 : start_pos = i + 1;
262 : :
263 [ + + ]: 336 : } while (*p);
264 : :
265 : 240 : *size = r;
266 : :
267 : 240 : return 0;
268 : : }
269 : :
270 : 416 : int parse_range(const char *t, unsigned *lower, unsigned *upper) {
271 : 416 : _cleanup_free_ char *word = NULL;
272 : : unsigned l, u;
273 : : int r;
274 : :
275 [ - + ]: 416 : assert(lower);
276 [ - + ]: 416 : assert(upper);
277 : :
278 : : /* Extract the lower bound. */
279 : 416 : r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
280 [ - + ]: 416 : if (r < 0)
281 : 0 : return r;
282 [ - + ]: 416 : if (r == 0)
283 : 0 : return -EINVAL;
284 : :
285 : 416 : r = safe_atou(word, &l);
286 [ + + ]: 416 : if (r < 0)
287 : 72 : return r;
288 : :
289 : : /* Check for the upper bound and extract it if needed */
290 [ + + ]: 344 : if (!t)
291 : : /* Single number with no dashes. */
292 : 208 : u = l;
293 [ + + ]: 136 : else if (!*t)
294 : : /* Trailing dash is an error. */
295 : 4 : return -EINVAL;
296 : : else {
297 : 132 : r = safe_atou(t, &u);
298 [ + + ]: 132 : if (r < 0)
299 : 44 : return r;
300 : : }
301 : :
302 : 296 : *lower = l;
303 : 296 : *upper = u;
304 : 296 : return 0;
305 : : }
306 : :
307 : 120 : int parse_errno(const char *t) {
308 : : int r, e;
309 : :
310 [ - + ]: 120 : assert(t);
311 : :
312 : 120 : r = errno_from_name(t);
313 [ + + ]: 120 : if (r > 0)
314 : 16 : return r;
315 : :
316 : 104 : r = safe_atoi(t, &e);
317 [ + + ]: 104 : if (r < 0)
318 : 60 : return r;
319 : :
320 : : /* 0 is also allowed here */
321 [ + + + + ]: 44 : if (!errno_is_valid(e) && e != 0)
322 : 20 : return -ERANGE;
323 : :
324 : 24 : return e;
325 : : }
326 : :
327 : 64 : int parse_syscall_and_errno(const char *in, char **name, int *error) {
328 : 64 : _cleanup_free_ char *n = NULL;
329 : : char *p;
330 : 64 : int e = -1;
331 : :
332 [ - + ]: 64 : assert(in);
333 [ - + ]: 64 : assert(name);
334 [ - + ]: 64 : assert(error);
335 : :
336 : : /*
337 : : * This parse "syscall:errno" like "uname:EILSEQ", "@sync:255".
338 : : * If errno is omitted, then error is set to -1.
339 : : * Empty syscall name is not allowed.
340 : : * Here, we do not check that the syscall name is valid or not.
341 : : */
342 : :
343 : 64 : p = strchr(in, ':');
344 [ + + ]: 64 : if (p) {
345 : 56 : e = parse_errno(p + 1);
346 [ + + ]: 56 : if (e < 0)
347 : 36 : return e;
348 : :
349 : 20 : n = strndup(in, p - in);
350 : : } else
351 : 8 : n = strdup(in);
352 : :
353 [ - + ]: 28 : if (!n)
354 : 0 : return -ENOMEM;
355 : :
356 [ + + ]: 28 : if (isempty(n))
357 : 8 : return -EINVAL;
358 : :
359 : 20 : *error = e;
360 : 20 : *name = TAKE_PTR(n);
361 : :
362 : 20 : return 0;
363 : : }
364 : :
365 : 419236 : int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
366 : 419236 : char *x = NULL;
367 : : unsigned long l;
368 : :
369 [ - + ]: 419236 : assert(s);
370 [ - + ]: 419236 : assert(ret_u);
371 [ - + ]: 419236 : assert(base <= 16);
372 : :
373 : : /* strtoul() is happy to parse negative values, and silently
374 : : * converts them to unsigned values without generating an
375 : : * error. We want a clean error, hence let's look for the "-"
376 : : * prefix on our own, and generate an error. But let's do so
377 : : * only after strtoul() validated that the string is clean
378 : : * otherwise, so that we return EINVAL preferably over
379 : : * ERANGE. */
380 : :
381 : 419236 : s += strspn(s, WHITESPACE);
382 : :
383 : 419236 : errno = 0;
384 : 419236 : l = strtoul(s, &x, base);
385 [ + + ]: 419236 : if (errno > 0)
386 : 8 : return -errno;
387 [ + - + + : 419228 : if (!x || x == s || *x != 0)
+ + ]
388 : 452 : return -EINVAL;
389 [ + + ]: 418776 : if (s[0] == '-')
390 : 16 : return -ERANGE;
391 [ - + ]: 418760 : if ((unsigned long) (unsigned) l != l)
392 : 0 : return -ERANGE;
393 : :
394 : 418760 : *ret_u = (unsigned) l;
395 : 418760 : return 0;
396 : : }
397 : :
398 : 3472 : int safe_atoi(const char *s, int *ret_i) {
399 : 3472 : char *x = NULL;
400 : : long l;
401 : :
402 [ - + ]: 3472 : assert(s);
403 [ - + ]: 3472 : assert(ret_i);
404 : :
405 : 3472 : errno = 0;
406 : 3472 : l = strtol(s, &x, 0);
407 [ + + ]: 3472 : if (errno > 0)
408 : 8 : return -errno;
409 [ + - + + : 3464 : if (!x || x == s || *x != 0)
+ + ]
410 : 924 : return -EINVAL;
411 [ + + ]: 2540 : if ((long) (int) l != l)
412 : 12 : return -ERANGE;
413 : :
414 : 2528 : *ret_i = (int) l;
415 : 2528 : return 0;
416 : : }
417 : :
418 : 12626 : int safe_atollu(const char *s, long long unsigned *ret_llu) {
419 : 12626 : char *x = NULL;
420 : : unsigned long long l;
421 : :
422 [ - + ]: 12626 : assert(s);
423 [ - + ]: 12626 : assert(ret_llu);
424 : :
425 : 12626 : s += strspn(s, WHITESPACE);
426 : :
427 : 12626 : errno = 0;
428 : 12626 : l = strtoull(s, &x, 0);
429 [ + + ]: 12626 : if (errno > 0)
430 : 8 : return -errno;
431 [ + - + + : 12618 : if (!x || x == s || *x != 0)
+ + ]
432 : 80 : return -EINVAL;
433 [ + + ]: 12538 : if (*s == '-')
434 : 12 : return -ERANGE;
435 : :
436 : 12526 : *ret_llu = l;
437 : 12526 : return 0;
438 : : }
439 : :
440 : 80 : int safe_atolli(const char *s, long long int *ret_lli) {
441 : 80 : char *x = NULL;
442 : : long long l;
443 : :
444 [ - + ]: 80 : assert(s);
445 [ - + ]: 80 : assert(ret_lli);
446 : :
447 : 80 : errno = 0;
448 : 80 : l = strtoll(s, &x, 0);
449 [ + + ]: 80 : if (errno > 0)
450 : 16 : return -errno;
451 [ + - + + : 64 : if (!x || x == s || *x != 0)
+ + ]
452 : 32 : return -EINVAL;
453 : :
454 : 32 : *ret_lli = l;
455 : 32 : return 0;
456 : : }
457 : :
458 : 460 : int safe_atou8(const char *s, uint8_t *ret) {
459 : 460 : char *x = NULL;
460 : : unsigned long l;
461 : :
462 [ - + ]: 460 : assert(s);
463 [ - + ]: 460 : assert(ret);
464 : :
465 : 460 : s += strspn(s, WHITESPACE);
466 : :
467 : 460 : errno = 0;
468 : 460 : l = strtoul(s, &x, 0);
469 [ - + ]: 460 : if (errno > 0)
470 : 0 : return -errno;
471 [ + - + + : 460 : if (!x || x == s || *x != 0)
- + ]
472 : 4 : return -EINVAL;
473 [ + + ]: 456 : if (s[0] == '-')
474 : 20 : return -ERANGE;
475 [ + + ]: 436 : if ((unsigned long) (uint8_t) l != l)
476 : 4 : return -ERANGE;
477 : :
478 : 432 : *ret = (uint8_t) l;
479 : 432 : return 0;
480 : : }
481 : :
482 : 208 : int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
483 : 208 : char *x = NULL;
484 : : unsigned long l;
485 : :
486 [ - + ]: 208 : assert(s);
487 [ - + ]: 208 : assert(ret);
488 [ - + ]: 208 : assert(base <= 16);
489 : :
490 : 208 : s += strspn(s, WHITESPACE);
491 : :
492 : 208 : errno = 0;
493 : 208 : l = strtoul(s, &x, base);
494 [ - + ]: 208 : if (errno > 0)
495 : 0 : return -errno;
496 [ + - + + : 208 : if (!x || x == s || *x != 0)
+ + ]
497 : 56 : return -EINVAL;
498 [ + + ]: 152 : if (s[0] == '-')
499 : 16 : return -ERANGE;
500 [ + + ]: 136 : if ((unsigned long) (uint16_t) l != l)
501 : 20 : return -ERANGE;
502 : :
503 : 116 : *ret = (uint16_t) l;
504 : 116 : return 0;
505 : : }
506 : :
507 : 40 : int safe_atoi16(const char *s, int16_t *ret) {
508 : 40 : char *x = NULL;
509 : : long l;
510 : :
511 [ - + ]: 40 : assert(s);
512 [ - + ]: 40 : assert(ret);
513 : :
514 : 40 : errno = 0;
515 : 40 : l = strtol(s, &x, 0);
516 [ - + ]: 40 : if (errno > 0)
517 : 0 : return -errno;
518 [ + - + + : 40 : if (!x || x == s || *x != 0)
+ + ]
519 : 16 : return -EINVAL;
520 [ + + ]: 24 : if ((long) (int16_t) l != l)
521 : 8 : return -ERANGE;
522 : :
523 : 16 : *ret = (int16_t) l;
524 : 16 : return 0;
525 : : }
526 : :
527 : 40 : int safe_atod(const char *s, double *ret_d) {
528 : 40 : _cleanup_(freelocalep) locale_t loc = (locale_t) 0;
529 : 40 : char *x = NULL;
530 : 40 : double d = 0;
531 : :
532 [ - + ]: 40 : assert(s);
533 [ - + ]: 40 : assert(ret_d);
534 : :
535 : 40 : loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
536 [ - + ]: 40 : if (loc == (locale_t) 0)
537 : 0 : return -errno;
538 : :
539 : 40 : errno = 0;
540 : 40 : d = strtod_l(s, &x, loc);
541 [ - + ]: 40 : if (errno > 0)
542 : 0 : return -errno;
543 [ + - + + : 40 : if (!x || x == s || *x != 0)
+ + ]
544 : 28 : return -EINVAL;
545 : :
546 : 12 : *ret_d = (double) d;
547 : 12 : return 0;
548 : : }
549 : :
550 : 821 : int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
551 : : size_t i;
552 : 821 : unsigned val = 0;
553 : : const char *s;
554 : :
555 : 821 : s = *p;
556 : :
557 : : /* accept any number of digits, strtoull is limited to 19 */
558 [ + + ]: 5507 : for (i=0; i < digits; i++,s++) {
559 [ + + - + ]: 4742 : if (*s < '0' || *s > '9') {
560 [ - + ]: 56 : if (i == 0)
561 : 0 : return -EINVAL;
562 : :
563 : : /* too few digits, pad with 0 */
564 [ + + ]: 296 : for (; i < digits; i++)
565 : 240 : val *= 10;
566 : :
567 : 56 : break;
568 : : }
569 : :
570 : 4686 : val *= 10;
571 : 4686 : val += *s - '0';
572 : : }
573 : :
574 : : /* maybe round up */
575 [ + + + - ]: 821 : if (*s >= '5' && *s <= '9')
576 : 16 : val++;
577 : :
578 : 821 : s += strspn(s, DIGITS);
579 : :
580 : 821 : *p = s;
581 : 821 : *res = val;
582 : :
583 : 821 : return 0;
584 : : }
585 : :
586 : 72 : int parse_percent_unbounded(const char *p) {
587 : : const char *pc, *n;
588 : : int r, v;
589 : :
590 : 72 : pc = endswith(p, "%");
591 [ + + ]: 72 : if (!pc)
592 : 28 : return -EINVAL;
593 : :
594 : 44 : n = strndupa(p, pc - p);
595 : 44 : r = safe_atoi(n, &v);
596 [ + + ]: 44 : if (r < 0)
597 : 16 : return r;
598 [ + + ]: 28 : if (v < 0)
599 : 4 : return -ERANGE;
600 : :
601 : 24 : return v;
602 : : }
603 : :
604 : 64 : int parse_percent(const char *p) {
605 : : int v;
606 : :
607 : 64 : v = parse_percent_unbounded(p);
608 [ + + ]: 64 : if (v > 100)
609 : 4 : return -ERANGE;
610 : :
611 : 60 : return v;
612 : : }
613 : :
614 : 184 : int parse_permille_unbounded(const char *p) {
615 : : const char *pc, *pm, *dot, *n;
616 : : int r, q, v;
617 : :
618 : 184 : pm = endswith(p, "‰");
619 [ + + ]: 184 : if (pm) {
620 : 60 : n = strndupa(p, pm - p);
621 : 60 : r = safe_atoi(n, &v);
622 [ + + ]: 60 : if (r < 0)
623 : 28 : return r;
624 [ + + ]: 32 : if (v < 0)
625 : 4 : return -ERANGE;
626 : : } else {
627 : 124 : pc = endswith(p, "%");
628 [ + + ]: 124 : if (!pc)
629 : 60 : return -EINVAL;
630 : :
631 : 64 : dot = memchr(p, '.', pc - p);
632 [ + + ]: 64 : if (dot) {
633 [ + + ]: 24 : if (dot + 2 != pc)
634 : 4 : return -EINVAL;
635 [ + - - + ]: 20 : if (dot[1] < '0' || dot[1] > '9')
636 : 0 : return -EINVAL;
637 : 20 : q = dot[1] - '0';
638 : 20 : n = strndupa(p, dot - p);
639 : : } else {
640 : 40 : q = 0;
641 : 40 : n = strndupa(p, pc - p);
642 : : }
643 : 60 : r = safe_atoi(n, &v);
644 [ + + ]: 60 : if (r < 0)
645 : 12 : return r;
646 [ + + ]: 48 : if (v < 0)
647 : 4 : return -ERANGE;
648 [ + + ]: 44 : if (v > (INT_MAX - q) / 10)
649 : 12 : return -ERANGE;
650 : :
651 : 32 : v = v * 10 + q;
652 : : }
653 : :
654 : 60 : return v;
655 : : }
656 : :
657 : 136 : int parse_permille(const char *p) {
658 : : int v;
659 : :
660 : 136 : v = parse_permille_unbounded(p);
661 [ + + ]: 136 : if (v > 1000)
662 : 8 : return -ERANGE;
663 : :
664 : 128 : return v;
665 : : }
666 : :
667 : 84 : int parse_nice(const char *p, int *ret) {
668 : : int n, r;
669 : :
670 : 84 : r = safe_atoi(p, &n);
671 [ + + ]: 84 : if (r < 0)
672 : 16 : return r;
673 : :
674 [ + + ]: 68 : if (!nice_is_valid(n))
675 : 24 : return -ERANGE;
676 : :
677 : 44 : *ret = n;
678 : 44 : return 0;
679 : : }
680 : :
681 : 132 : int parse_ip_port(const char *s, uint16_t *ret) {
682 : : uint16_t l;
683 : : int r;
684 : :
685 : 132 : r = safe_atou16(s, &l);
686 [ + + ]: 132 : if (r < 0)
687 : 36 : return r;
688 : :
689 [ + + ]: 96 : if (l == 0)
690 : 12 : return -EINVAL;
691 : :
692 : 84 : *ret = (uint16_t) l;
693 : :
694 : 84 : return 0;
695 : : }
696 : :
697 : 0 : int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high) {
698 : : unsigned l, h;
699 : : int r;
700 : :
701 : 0 : r = parse_range(s, &l, &h);
702 [ # # ]: 0 : if (r < 0)
703 : 0 : return r;
704 : :
705 [ # # # # : 0 : if (l <= 0 || l > 65535 || h <= 0 || h > 65535)
# # # # ]
706 : 0 : return -EINVAL;
707 : :
708 [ # # ]: 0 : if (h < l)
709 : 0 : return -EINVAL;
710 : :
711 : 0 : *low = l;
712 : 0 : *high = h;
713 : :
714 : 0 : return 0;
715 : : }
716 : :
717 : 1952 : int parse_dev(const char *s, dev_t *ret) {
718 : : const char *major;
719 : : unsigned x, y;
720 : : size_t n;
721 : : int r;
722 : :
723 : 1952 : n = strspn(s, DIGITS);
724 [ + + ]: 1952 : if (n == 0)
725 : 16 : return -EINVAL;
726 [ + + ]: 1936 : if (s[n] != ':')
727 : 8 : return -EINVAL;
728 : :
729 : 1928 : major = strndupa(s, n);
730 : 1928 : r = safe_atou(major, &x);
731 [ - + ]: 1928 : if (r < 0)
732 : 0 : return r;
733 : :
734 : 1928 : r = safe_atou(s + n + 1, &y);
735 [ + + ]: 1928 : if (r < 0)
736 : 4 : return r;
737 : :
738 [ + - + - : 1924 : if (!DEVICE_MAJOR_VALID(x) || !DEVICE_MINOR_VALID(y))
+ - + - +
- - + ]
739 : 0 : return -ERANGE;
740 : :
741 : 1924 : *ret = makedev(x, y);
742 : 1924 : return 0;
743 : : }
744 : :
745 : 0 : int parse_oom_score_adjust(const char *s, int *ret) {
746 : : int r, v;
747 : :
748 [ # # ]: 0 : assert(s);
749 [ # # ]: 0 : assert(ret);
750 : :
751 : 0 : r = safe_atoi(s, &v);
752 [ # # ]: 0 : if (r < 0)
753 : 0 : return r;
754 : :
755 [ # # # # ]: 0 : if (v < OOM_SCORE_ADJ_MIN || v > OOM_SCORE_ADJ_MAX)
756 : 0 : return -ERANGE;
757 : :
758 : 0 : *ret = v;
759 : 0 : return 0;
760 : : }
|