Coverage Report

Created: 2019-06-19 13:33

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