chiark / gitweb /
tree-wide: remove Lennart's copyright lines
[elogind.git] / src / basic / parse-util.c
index c38e14d96a367e5329b6dda480ea4e50e7377bcf..f33e12a74a25c480223c28527bf7258a24c6173e 100644 (file)
@@ -1,21 +1,4 @@
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include <errno.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+//#include <sys/socket.h>
 
 #include "alloc-util.h"
+#include "errno-list.h"
 //#include "extract-word.h"
+#include "locale-util.h"
 #include "macro.h"
+//#include "missing.h"
 #include "parse-util.h"
+#include "process-util.h"
 #include "string-util.h"
 
 /// Additional includes needed by elogind
@@ -61,7 +49,7 @@ int parse_pid(const char *s, pid_t* ret_pid) {
         if ((unsigned long) pid != ul)
                 return -ERANGE;
 
-        if (pid <= 0)
+        if (!pid_is_valid(pid))
                 return -ERANGE;
 
         *ret_pid = pid;
@@ -83,7 +71,7 @@ int parse_mode(const char *s, mode_t *ret) {
         l = strtol(s, &x, 8);
         if (errno > 0)
                 return -errno;
-        if (!x || x == s || *x)
+        if (!x || x == s || *x != 0)
                 return -EINVAL;
         if (l < 0 || l  > 07777)
                 return -ERANGE;
@@ -105,6 +93,30 @@ int parse_ifindex(const char *s, int *ret) {
         return 0;
 }
 
+int parse_mtu(int family, const char *s, uint32_t *ret) {
+        uint64_t u;
+        size_t m;
+        int r;
+
+        r = parse_size(s, 1024, &u);
+        if (r < 0)
+                return r;
+
+        if (u > UINT32_MAX)
+                return -ERANGE;
+
+        if (family == AF_INET6)
+                m = IPV6_MIN_MTU; /* This is 1280 */
+        else
+                m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */
+
+        if (u < m)
+                return -ERANGE;
+
+        *ret = (uint32_t) u;
+        return 0;
+}
+
 int parse_size(const char *t, uint64_t base, uint64_t *size) {
 
         /* Soo, sometimes we want to parse IEC binary suffixes, and
@@ -154,7 +166,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
         unsigned n_entries, start_pos = 0;
 
         assert(t);
-        assert(base == 1000 || base == 1024);
+        assert(IN_SET(base, 1000, 1024));
         assert(size);
 
         if (base == 1000) {
@@ -272,6 +284,64 @@ int parse_range(const char *t, unsigned *lower, unsigned *upper) {
 }
 #endif // 0
 
+int parse_errno(const char *t) {
+        int r, e;
+
+        assert(t);
+
+        r = errno_from_name(t);
+        if (r > 0)
+                return r;
+
+        r = safe_atoi(t, &e);
+        if (r < 0)
+                return r;
+
+        /* 0 is also allowed here */
+        if (!errno_is_valid(e) && e != 0)
+                return -ERANGE;
+
+        return e;
+}
+
+int parse_syscall_and_errno(const char *in, char **name, int *error) {
+        _cleanup_free_ char *n = NULL;
+        char *p;
+        int e = -1;
+
+        assert(in);
+        assert(name);
+        assert(error);
+
+        /*
+         * This parse "syscall:errno" like "uname:EILSEQ", "@sync:255".
+         * If errno is omitted, then error is set to -1.
+         * Empty syscall name is not allowed.
+         * Here, we do not check that the syscall name is valid or not.
+         */
+
+        p = strchr(in, ':');
+        if (p) {
+                e = parse_errno(p + 1);
+                if (e < 0)
+                        return e;
+
+                n = strndup(in, p - in);
+        } else
+                n = strdup(in);
+
+        if (!n)
+                return -ENOMEM;
+
+        if (isempty(n))
+                return -EINVAL;
+
+        *error = e;
+        *name = TAKE_PTR(n);
+
+        return 0;
+}
+
 char *format_bytes(char *buf, size_t l, uint64_t t) {
         unsigned i;
 
@@ -313,12 +383,13 @@ finish:
 
 }
 
-int safe_atou(const char *s, unsigned *ret_u) {
+int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
         char *x = NULL;
         unsigned long l;
 
         assert(s);
         assert(ret_u);
+        assert(base <= 16);
 
         /* strtoul() is happy to parse negative values, and silently
          * converts them to unsigned values without generating an
@@ -331,10 +402,10 @@ int safe_atou(const char *s, unsigned *ret_u) {
         s += strspn(s, WHITESPACE);
 
         errno = 0;
-        l = strtoul(s, &x, 0);
+        l = strtoul(s, &x, base);
         if (errno > 0)
                 return -errno;
-        if (!x || x == s || *x)
+        if (!x || x == s || *x != 0)
                 return -EINVAL;
         if (s[0] == '-')
                 return -ERANGE;
@@ -356,7 +427,7 @@ int safe_atoi(const char *s, int *ret_i) {
         l = strtol(s, &x, 0);
         if (errno > 0)
                 return -errno;
-        if (!x || x == s || *x)
+        if (!x || x == s || *x != 0)
                 return -EINVAL;
         if ((long) (int) l != l)
                 return -ERANGE;
@@ -378,7 +449,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
         l = strtoull(s, &x, 0);
         if (errno > 0)
                 return -errno;
-        if (!x || x == s || *x)
+        if (!x || x == s || *x != 0)
                 return -EINVAL;
         if (*s == '-')
                 return -ERANGE;
@@ -398,7 +469,7 @@ int safe_atolli(const char *s, long long int *ret_lli) {
         l = strtoll(s, &x, 0);
         if (errno > 0)
                 return -errno;
-        if (!x || x == s || *x)
+        if (!x || x == s || *x != 0)
                 return -EINVAL;
 
         *ret_lli = l;
@@ -418,7 +489,7 @@ int safe_atou8(const char *s, uint8_t *ret) {
         l = strtoul(s, &x, 0);
         if (errno > 0)
                 return -errno;
-        if (!x || x == s || *x)
+        if (!x || x == s || *x != 0)
                 return -EINVAL;
         if (s[0] == '-')
                 return -ERANGE;
@@ -429,20 +500,21 @@ int safe_atou8(const char *s, uint8_t *ret) {
         return 0;
 }
 
-int safe_atou16(const char *s, uint16_t *ret) {
+int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
         char *x = NULL;
         unsigned long l;
 
         assert(s);
         assert(ret);
+        assert(base <= 16);
 
         s += strspn(s, WHITESPACE);
 
         errno = 0;
-        l = strtoul(s, &x, 0);
+        l = strtoul(s, &x, base);
         if (errno > 0)
                 return -errno;
-        if (!x || x == s || *x)
+        if (!x || x == s || *x != 0)
                 return -EINVAL;
         if (s[0] == '-')
                 return -ERANGE;
@@ -464,7 +536,7 @@ int safe_atoi16(const char *s, int16_t *ret) {
         l = strtol(s, &x, 0);
         if (errno > 0)
                 return -errno;
-        if (!x || x == s || *x)
+        if (!x || x == s || *x != 0)
                 return -EINVAL;
         if ((long) (int16_t) l != l)
                 return -ERANGE;
@@ -474,9 +546,9 @@ int safe_atoi16(const char *s, int16_t *ret) {
 }
 
 int safe_atod(const char *s, double *ret_d) {
+        _cleanup_(freelocalep) locale_t loc = (locale_t) 0;
         char *x = NULL;
         double d = 0;
-        locale_t loc;
 
         assert(s);
         assert(ret_d);
@@ -487,16 +559,11 @@ int safe_atod(const char *s, double *ret_d) {
 
         errno = 0;
         d = strtod_l(s, &x, loc);
-        if (errno > 0) {
-                freelocale(loc);
+        if (errno > 0)
                 return -errno;
-        }
-        if (!x || x == s || *x) {
-                freelocale(loc);
+        if (!x || x == s || *x != 0)
                 return -EINVAL;
-        }
 
-        freelocale(loc);
         *ret_d = (double) d;
         return 0;
 }
@@ -539,19 +606,20 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
 
 int parse_percent_unbounded(const char *p) {
         const char *pc, *n;
-        unsigned v;
-        int r;
+        int r, v;
 
         pc = endswith(p, "%");
         if (!pc)
                 return -EINVAL;
 
         n = strndupa(p, pc - p);
-        r = safe_atou(n, &v);
+        r = safe_atoi(n, &v);
         if (r < 0)
                 return r;
+        if (v < 0)
+                return -ERANGE;
 
-        return (int) v;
+        return v;
 }
 
 int parse_percent(const char *p) {
@@ -564,6 +632,58 @@ int parse_percent(const char *p) {
         return v;
 }
 
+int parse_permille_unbounded(const char *p) {
+        const char *pc, *pm, *dot, *n;
+        int r, q, v;
+
+        pm = endswith(p, "‰");
+        if (pm) {
+                n = strndupa(p, pm - p);
+                r = safe_atoi(n, &v);
+                if (r < 0)
+                        return r;
+        } else {
+                pc = endswith(p, "%");
+                if (!pc)
+                        return -EINVAL;
+
+                dot = memchr(p, '.', pc - p);
+                if (dot) {
+                        if (dot + 2 != pc)
+                                return -EINVAL;
+                        if (dot[1] < '0' || dot[1] > '9')
+                                return -EINVAL;
+                        q = dot[1] - '0';
+                        n = strndupa(p, dot - p);
+                } else {
+                        q = 0;
+                        n = strndupa(p, pc - p);
+                }
+                r = safe_atoi(n, &v);
+                if (r < 0)
+                        return r;
+                if (v > (INT_MAX - q) / 10)
+                        return -ERANGE;
+
+                v = v * 10 + q;
+        }
+
+        if (v < 0)
+                return -ERANGE;
+
+        return v;
+}
+
+int parse_permille(const char *p) {
+        int v;
+
+        v = parse_permille_unbounded(p);
+        if (v > 1000)
+                return -ERANGE;
+
+        return v;
+}
+
 #if 0 /// UNNEEDED by elogind
 int parse_nice(const char *p, int *ret) {
         int n, r;
@@ -595,3 +715,35 @@ int parse_ip_port(const char *s, uint16_t *ret) {
         return 0;
 }
 #endif // 0
+
+int parse_dev(const char *s, dev_t *ret) {
+        unsigned x, y;
+        dev_t d;
+
+        if (sscanf(s, "%u:%u", &x, &y) != 2)
+                return -EINVAL;
+
+        d = makedev(x, y);
+        if ((unsigned) major(d) != x || (unsigned) minor(d) != y)
+                return -EINVAL;
+
+        *ret = d;
+        return 0;
+}
+
+int parse_oom_score_adjust(const char *s, int *ret) {
+        int r, v;
+
+        assert(s);
+        assert(ret);
+
+        r = safe_atoi(s, &v);
+        if (r < 0)
+                return r;
+
+        if (v < OOM_SCORE_ADJ_MIN || v > OOM_SCORE_ADJ_MAX)
+                return -ERANGE;
+
+        *ret = v;
+        return 0;
+}