LCOV - code coverage report
Current view: top level - basic - parse-util.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 371 422 87.9 %
Date: 2019-08-22 15:41:25 Functions: 25 28 89.3 %

          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         226 : int parse_boolean(const char *v) {
      25         226 :         if (!v)
      26           0 :                 return -EINVAL;
      27             : 
      28         226 :         if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
      29          66 :                 return 1;
      30         160 :         else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
      31          78 :                 return 0;
      32             : 
      33          82 :         return -EINVAL;
      34             : }
      35             : 
      36         287 : int parse_pid(const char *s, pid_t* ret_pid) {
      37         287 :         unsigned long ul = 0;
      38             :         pid_t pid;
      39             :         int r;
      40             : 
      41         287 :         assert(s);
      42         287 :         assert(ret_pid);
      43             : 
      44         287 :         r = safe_atolu(s, &ul);
      45         287 :         if (r < 0)
      46          15 :                 return r;
      47             : 
      48         272 :         pid = (pid_t) ul;
      49             : 
      50         272 :         if ((unsigned long) pid != ul)
      51           0 :                 return -ERANGE;
      52             : 
      53         272 :         if (!pid_is_valid(pid))
      54           1 :                 return -ERANGE;
      55             : 
      56         271 :         *ret_pid = pid;
      57         271 :         return 0;
      58             : }
      59             : 
      60          16 : int parse_mode(const char *s, mode_t *ret) {
      61             :         char *x;
      62             :         long l;
      63             : 
      64          16 :         assert(s);
      65          16 :         assert(ret);
      66             : 
      67          16 :         s += strspn(s, WHITESPACE);
      68          16 :         if (s[0] == '-')
      69           2 :                 return -ERANGE;
      70             : 
      71          14 :         errno = 0;
      72          14 :         l = strtol(s, &x, 8);
      73          14 :         if (errno > 0)
      74           0 :                 return -errno;
      75          14 :         if (!x || x == s || *x != 0)
      76           6 :                 return -EINVAL;
      77           8 :         if (l < 0 || l  > 07777)
      78           1 :                 return -ERANGE;
      79             : 
      80           7 :         *ret = (mode_t) l;
      81           7 :         return 0;
      82             : }
      83             : 
      84         180 : int parse_ifindex(const char *s, int *ret) {
      85             :         int ifi, r;
      86             : 
      87         180 :         assert(s);
      88         180 :         assert(ret);
      89             : 
      90         180 :         r = safe_atoi(s, &ifi);
      91         180 :         if (r < 0)
      92           2 :                 return r;
      93         178 :         if (ifi <= 0)
      94           0 :                 return -EINVAL;
      95             : 
      96         178 :         *ret = ifi;
      97         178 :         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          28 : int parse_mtu(int family, const char *s, uint32_t *ret) {
     119             :         uint64_t u;
     120             :         size_t m;
     121             :         int r;
     122             : 
     123          28 :         r = parse_size(s, 1024, &u);
     124          28 :         if (r < 0)
     125           7 :                 return r;
     126             : 
     127          21 :         if (u > UINT32_MAX)
     128           2 :                 return -ERANGE;
     129             : 
     130          19 :         if (family == AF_INET6)
     131           3 :                 m = IPV6_MIN_MTU; /* This is 1280 */
     132             :         else
     133          16 :                 m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */
     134             : 
     135          19 :         if (u < m)
     136           4 :                 return -ERANGE;
     137             : 
     138          15 :         *ret = (uint32_t) u;
     139          15 :         return 0;
     140             : }
     141             : 
     142          88 : 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          88 :         unsigned long long r = 0;
     188          88 :         unsigned n_entries, start_pos = 0;
     189             : 
     190          88 :         assert(t);
     191          88 :         assert(IN_SET(base, 1000, 1024));
     192          88 :         assert(size);
     193             : 
     194          88 :         if (base == 1000) {
     195           9 :                 table = si;
     196           9 :                 n_entries = ELEMENTSOF(si);
     197             :         } else {
     198          79 :                 table = iec;
     199          79 :                 n_entries = ELEMENTSOF(iec);
     200             :         }
     201             : 
     202          88 :         p = t;
     203             :         do {
     204             :                 unsigned long long l, tmp;
     205         112 :                 double frac = 0;
     206             :                 char *e;
     207             :                 unsigned i;
     208             : 
     209         112 :                 p += strspn(p, WHITESPACE);
     210             : 
     211         112 :                 errno = 0;
     212         112 :                 l = strtoull(p, &e, 10);
     213         112 :                 if (errno > 0)
     214          28 :                         return -errno;
     215         110 :                 if (e == p)
     216          17 :                         return -EINVAL;
     217          93 :                 if (*p == '-')
     218           7 :                         return -ERANGE;
     219             : 
     220          86 :                 if (*e == '.') {
     221          19 :                         e++;
     222             : 
     223             :                         /* strtoull() itself would accept space/+/- */
     224          19 :                         if (*e >= '0' && *e <= '9') {
     225             :                                 unsigned long long l2;
     226             :                                 char *e2;
     227             : 
     228          17 :                                 l2 = strtoull(e, &e2, 10);
     229          17 :                                 if (errno > 0)
     230           0 :                                         return -errno;
     231             : 
     232             :                                 /* Ignore failure. E.g. 10.M is valid */
     233          17 :                                 frac = l2;
     234          40 :                                 for (; e < e2; e++)
     235          23 :                                         frac /= 10;
     236             :                         }
     237             :                 }
     238             : 
     239          86 :                 e += strspn(e, WHITESPACE);
     240             : 
     241         514 :                 for (i = start_pos; i < n_entries; i++)
     242         513 :                         if (startswith(e, table[i].suffix))
     243          85 :                                 break;
     244             : 
     245          86 :                 if (i >= n_entries)
     246           1 :                         return -EINVAL;
     247             : 
     248          85 :                 if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
     249           1 :                         return -ERANGE;
     250             : 
     251          84 :                 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
     252          84 :                 if (tmp > ULLONG_MAX - r)
     253           0 :                         return -ERANGE;
     254             : 
     255          84 :                 r += tmp;
     256             :                 if ((unsigned long long) (uint64_t) r != r)
     257             :                         return -ERANGE;
     258             : 
     259          84 :                 p = e + strlen(table[i].suffix);
     260             : 
     261          84 :                 start_pos = i + 1;
     262             : 
     263          84 :         } while (*p);
     264             : 
     265          60 :         *size = r;
     266             : 
     267          60 :         return 0;
     268             : }
     269             : 
     270         104 : int parse_range(const char *t, unsigned *lower, unsigned *upper) {
     271         104 :         _cleanup_free_ char *word = NULL;
     272             :         unsigned l, u;
     273             :         int r;
     274             : 
     275         104 :         assert(lower);
     276         104 :         assert(upper);
     277             : 
     278             :         /* Extract the lower bound. */
     279         104 :         r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
     280         104 :         if (r < 0)
     281           0 :                 return r;
     282         104 :         if (r == 0)
     283           0 :                 return -EINVAL;
     284             : 
     285         104 :         r = safe_atou(word, &l);
     286         104 :         if (r < 0)
     287          18 :                 return r;
     288             : 
     289             :         /* Check for the upper bound and extract it if needed */
     290          86 :         if (!t)
     291             :                 /* Single number with no dashes. */
     292          52 :                 u = l;
     293          34 :         else if (!*t)
     294             :                 /* Trailing dash is an error. */
     295           1 :                 return -EINVAL;
     296             :         else {
     297          33 :                 r = safe_atou(t, &u);
     298          33 :                 if (r < 0)
     299          11 :                         return r;
     300             :         }
     301             : 
     302          74 :         *lower = l;
     303          74 :         *upper = u;
     304          74 :         return 0;
     305             : }
     306             : 
     307          30 : int parse_errno(const char *t) {
     308             :         int r, e;
     309             : 
     310          30 :         assert(t);
     311             : 
     312          30 :         r = errno_from_name(t);
     313          30 :         if (r > 0)
     314           4 :                 return r;
     315             : 
     316          26 :         r = safe_atoi(t, &e);
     317          26 :         if (r < 0)
     318          15 :                 return r;
     319             : 
     320             :         /* 0 is also allowed here */
     321          11 :         if (!errno_is_valid(e) && e != 0)
     322           5 :                 return -ERANGE;
     323             : 
     324           6 :         return e;
     325             : }
     326             : 
     327          16 : int parse_syscall_and_errno(const char *in, char **name, int *error) {
     328          16 :         _cleanup_free_ char *n = NULL;
     329             :         char *p;
     330          16 :         int e = -1;
     331             : 
     332          16 :         assert(in);
     333          16 :         assert(name);
     334          16 :         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          16 :         p = strchr(in, ':');
     344          16 :         if (p) {
     345          14 :                 e = parse_errno(p + 1);
     346          14 :                 if (e < 0)
     347           9 :                         return e;
     348             : 
     349           5 :                 n = strndup(in, p - in);
     350             :         } else
     351           2 :                 n = strdup(in);
     352             : 
     353           7 :         if (!n)
     354           0 :                 return -ENOMEM;
     355             : 
     356           7 :         if (isempty(n))
     357           2 :                 return -EINVAL;
     358             : 
     359           5 :         *error = e;
     360           5 :         *name = TAKE_PTR(n);
     361             : 
     362           5 :         return 0;
     363             : }
     364             : 
     365      104890 : int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
     366      104890 :         char *x = NULL;
     367             :         unsigned long l;
     368             : 
     369      104890 :         assert(s);
     370      104890 :         assert(ret_u);
     371      104890 :         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      104890 :         s += strspn(s, WHITESPACE);
     382             : 
     383      104890 :         errno = 0;
     384      104890 :         l = strtoul(s, &x, base);
     385      104890 :         if (errno > 0)
     386           2 :                 return -errno;
     387      104888 :         if (!x || x == s || *x != 0)
     388         113 :                 return -EINVAL;
     389      104775 :         if (s[0] == '-')
     390           4 :                 return -ERANGE;
     391      104771 :         if ((unsigned long) (unsigned) l != l)
     392           0 :                 return -ERANGE;
     393             : 
     394      104771 :         *ret_u = (unsigned) l;
     395      104771 :         return 0;
     396             : }
     397             : 
     398         837 : int safe_atoi(const char *s, int *ret_i) {
     399         837 :         char *x = NULL;
     400             :         long l;
     401             : 
     402         837 :         assert(s);
     403         837 :         assert(ret_i);
     404             : 
     405         837 :         errno = 0;
     406         837 :         l = strtol(s, &x, 0);
     407         837 :         if (errno > 0)
     408           2 :                 return -errno;
     409         835 :         if (!x || x == s || *x != 0)
     410         231 :                 return -EINVAL;
     411         604 :         if ((long) (int) l != l)
     412           3 :                 return -ERANGE;
     413             : 
     414         601 :         *ret_i = (int) l;
     415         601 :         return 0;
     416             : }
     417             : 
     418        3170 : int safe_atollu(const char *s, long long unsigned *ret_llu) {
     419        3170 :         char *x = NULL;
     420             :         unsigned long long l;
     421             : 
     422        3170 :         assert(s);
     423        3170 :         assert(ret_llu);
     424             : 
     425        3170 :         s += strspn(s, WHITESPACE);
     426             : 
     427        3170 :         errno = 0;
     428        3170 :         l = strtoull(s, &x, 0);
     429        3170 :         if (errno > 0)
     430           2 :                 return -errno;
     431        3168 :         if (!x || x == s || *x != 0)
     432          20 :                 return -EINVAL;
     433        3148 :         if (*s == '-')
     434           3 :                 return -ERANGE;
     435             : 
     436        3145 :         *ret_llu = l;
     437        3145 :         return 0;
     438             : }
     439             : 
     440          20 : int safe_atolli(const char *s, long long int *ret_lli) {
     441          20 :         char *x = NULL;
     442             :         long long l;
     443             : 
     444          20 :         assert(s);
     445          20 :         assert(ret_lli);
     446             : 
     447          20 :         errno = 0;
     448          20 :         l = strtoll(s, &x, 0);
     449          20 :         if (errno > 0)
     450           4 :                 return -errno;
     451          16 :         if (!x || x == s || *x != 0)
     452           8 :                 return -EINVAL;
     453             : 
     454           8 :         *ret_lli = l;
     455           8 :         return 0;
     456             : }
     457             : 
     458         115 : int safe_atou8(const char *s, uint8_t *ret) {
     459         115 :         char *x = NULL;
     460             :         unsigned long l;
     461             : 
     462         115 :         assert(s);
     463         115 :         assert(ret);
     464             : 
     465         115 :         s += strspn(s, WHITESPACE);
     466             : 
     467         115 :         errno = 0;
     468         115 :         l = strtoul(s, &x, 0);
     469         115 :         if (errno > 0)
     470           0 :                 return -errno;
     471         115 :         if (!x || x == s || *x != 0)
     472           1 :                 return -EINVAL;
     473         114 :         if (s[0] == '-')
     474           5 :                 return -ERANGE;
     475         109 :         if ((unsigned long) (uint8_t) l != l)
     476           1 :                 return -ERANGE;
     477             : 
     478         108 :         *ret = (uint8_t) l;
     479         108 :         return 0;
     480             : }
     481             : 
     482          52 : int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
     483          52 :         char *x = NULL;
     484             :         unsigned long l;
     485             : 
     486          52 :         assert(s);
     487          52 :         assert(ret);
     488          52 :         assert(base <= 16);
     489             : 
     490          52 :         s += strspn(s, WHITESPACE);
     491             : 
     492          52 :         errno = 0;
     493          52 :         l = strtoul(s, &x, base);
     494          52 :         if (errno > 0)
     495           0 :                 return -errno;
     496          52 :         if (!x || x == s || *x != 0)
     497          14 :                 return -EINVAL;
     498          38 :         if (s[0] == '-')
     499           4 :                 return -ERANGE;
     500          34 :         if ((unsigned long) (uint16_t) l != l)
     501           5 :                 return -ERANGE;
     502             : 
     503          29 :         *ret = (uint16_t) l;
     504          29 :         return 0;
     505             : }
     506             : 
     507          10 : int safe_atoi16(const char *s, int16_t *ret) {
     508          10 :         char *x = NULL;
     509             :         long l;
     510             : 
     511          10 :         assert(s);
     512          10 :         assert(ret);
     513             : 
     514          10 :         errno = 0;
     515          10 :         l = strtol(s, &x, 0);
     516          10 :         if (errno > 0)
     517           0 :                 return -errno;
     518          10 :         if (!x || x == s || *x != 0)
     519           4 :                 return -EINVAL;
     520           6 :         if ((long) (int16_t) l != l)
     521           2 :                 return -ERANGE;
     522             : 
     523           4 :         *ret = (int16_t) l;
     524           4 :         return 0;
     525             : }
     526             : 
     527          10 : int safe_atod(const char *s, double *ret_d) {
     528          10 :         _cleanup_(freelocalep) locale_t loc = (locale_t) 0;
     529          10 :         char *x = NULL;
     530          10 :         double d = 0;
     531             : 
     532          10 :         assert(s);
     533          10 :         assert(ret_d);
     534             : 
     535          10 :         loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
     536          10 :         if (loc == (locale_t) 0)
     537           0 :                 return -errno;
     538             : 
     539          10 :         errno = 0;
     540          10 :         d = strtod_l(s, &x, loc);
     541          10 :         if (errno > 0)
     542           0 :                 return -errno;
     543          10 :         if (!x || x == s || *x != 0)
     544           7 :                 return -EINVAL;
     545             : 
     546           3 :         *ret_d = (double) d;
     547           3 :         return 0;
     548             : }
     549             : 
     550         222 : int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
     551             :         size_t i;
     552         222 :         unsigned val = 0;
     553             :         const char *s;
     554             : 
     555         222 :         s = *p;
     556             : 
     557             :         /* accept any number of digits, strtoull is limited to 19 */
     558        1494 :         for (i=0; i < digits; i++,s++) {
     559        1286 :                 if (*s < '0' || *s > '9') {
     560          14 :                         if (i == 0)
     561           0 :                                 return -EINVAL;
     562             : 
     563             :                         /* too few digits, pad with 0 */
     564          74 :                         for (; i < digits; i++)
     565          60 :                                 val *= 10;
     566             : 
     567          14 :                         break;
     568             :                 }
     569             : 
     570        1272 :                 val *= 10;
     571        1272 :                 val += *s - '0';
     572             :         }
     573             : 
     574             :         /* maybe round up */
     575         222 :         if (*s >= '5' && *s <= '9')
     576           4 :                 val++;
     577             : 
     578         222 :         s += strspn(s, DIGITS);
     579             : 
     580         222 :         *p = s;
     581         222 :         *res = val;
     582             : 
     583         222 :         return 0;
     584             : }
     585             : 
     586          18 : int parse_percent_unbounded(const char *p) {
     587             :         const char *pc, *n;
     588             :         int r, v;
     589             : 
     590          18 :         pc = endswith(p, "%");
     591          18 :         if (!pc)
     592           7 :                 return -EINVAL;
     593             : 
     594          11 :         n = strndupa(p, pc - p);
     595          11 :         r = safe_atoi(n, &v);
     596          11 :         if (r < 0)
     597           4 :                 return r;
     598           7 :         if (v < 0)
     599           1 :                 return -ERANGE;
     600             : 
     601           6 :         return v;
     602             : }
     603             : 
     604          16 : int parse_percent(const char *p) {
     605             :         int v;
     606             : 
     607          16 :         v = parse_percent_unbounded(p);
     608          16 :         if (v > 100)
     609           1 :                 return -ERANGE;
     610             : 
     611          15 :         return v;
     612             : }
     613             : 
     614          46 : int parse_permille_unbounded(const char *p) {
     615             :         const char *pc, *pm, *dot, *n;
     616             :         int r, q, v;
     617             : 
     618          46 :         pm = endswith(p, "‰");
     619          46 :         if (pm) {
     620          15 :                 n = strndupa(p, pm - p);
     621          15 :                 r = safe_atoi(n, &v);
     622          15 :                 if (r < 0)
     623           7 :                         return r;
     624           8 :                 if (v < 0)
     625           1 :                         return -ERANGE;
     626             :         } else {
     627          31 :                 pc = endswith(p, "%");
     628          31 :                 if (!pc)
     629          15 :                         return -EINVAL;
     630             : 
     631          16 :                 dot = memchr(p, '.', pc - p);
     632          16 :                 if (dot) {
     633           6 :                         if (dot + 2 != pc)
     634           1 :                                 return -EINVAL;
     635           5 :                         if (dot[1] < '0' || dot[1] > '9')
     636           0 :                                 return -EINVAL;
     637           5 :                         q = dot[1] - '0';
     638           5 :                         n = strndupa(p, dot - p);
     639             :                 } else {
     640          10 :                         q = 0;
     641          10 :                         n = strndupa(p, pc - p);
     642             :                 }
     643          15 :                 r = safe_atoi(n, &v);
     644          15 :                 if (r < 0)
     645           3 :                         return r;
     646          12 :                 if (v < 0)
     647           1 :                         return -ERANGE;
     648          11 :                 if (v > (INT_MAX - q) / 10)
     649           3 :                         return -ERANGE;
     650             : 
     651           8 :                 v = v * 10 + q;
     652             :         }
     653             : 
     654          15 :         return v;
     655             : }
     656             : 
     657          34 : int parse_permille(const char *p) {
     658             :         int v;
     659             : 
     660          34 :         v = parse_permille_unbounded(p);
     661          34 :         if (v > 1000)
     662           2 :                 return -ERANGE;
     663             : 
     664          32 :         return v;
     665             : }
     666             : 
     667          21 : int parse_nice(const char *p, int *ret) {
     668             :         int n, r;
     669             : 
     670          21 :         r = safe_atoi(p, &n);
     671          21 :         if (r < 0)
     672           4 :                 return r;
     673             : 
     674          17 :         if (!nice_is_valid(n))
     675           6 :                 return -ERANGE;
     676             : 
     677          11 :         *ret = n;
     678          11 :         return 0;
     679             : }
     680             : 
     681          33 : int parse_ip_port(const char *s, uint16_t *ret) {
     682             :         uint16_t l;
     683             :         int r;
     684             : 
     685          33 :         r = safe_atou16(s, &l);
     686          33 :         if (r < 0)
     687           9 :                 return r;
     688             : 
     689          24 :         if (l == 0)
     690           3 :                 return -EINVAL;
     691             : 
     692          21 :         *ret = (uint16_t) l;
     693             : 
     694          21 :         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         488 : 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         488 :         n = strspn(s, DIGITS);
     724         488 :         if (n == 0)
     725           4 :                 return -EINVAL;
     726         484 :         if (s[n] != ':')
     727           2 :                 return -EINVAL;
     728             : 
     729         482 :         major = strndupa(s, n);
     730         482 :         r = safe_atou(major, &x);
     731         482 :         if (r < 0)
     732           0 :                 return r;
     733             : 
     734         482 :         r = safe_atou(s + n + 1, &y);
     735         482 :         if (r < 0)
     736           1 :                 return r;
     737             : 
     738         481 :         if (!DEVICE_MAJOR_VALID(x) || !DEVICE_MINOR_VALID(y))
     739           0 :                 return -ERANGE;
     740             : 
     741         481 :         *ret = makedev(x, y);
     742         481 :         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             : }

Generated by: LCOV version 1.14