]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/parse-util.c
Merge pull request #30284 from YHNdnzj/fstab-wantedby-defaultdeps
[thirdparty/systemd.git] / src / basic / parse-util.c
index 787a681870e6793a2641f415a5475766f7a39ec6..0430e33e40df55e22c3773dda826252657430530 100644 (file)
@@ -44,13 +44,30 @@ int parse_boolean(const char *v) {
         return -EINVAL;
 }
 
+int parse_tristate_full(const char *v, const char *third, int *ret) {
+        int r;
+
+        if (isempty(v) || streq_ptr(v, third)) { /* Empty string is always taken as the third/invalid/auto state */
+                if (ret)
+                        *ret = -1;
+        } else {
+                r = parse_boolean(v);
+                if (r < 0)
+                        return r;
+
+                if (ret)
+                        *ret = r;
+        }
+
+        return 0;
+}
+
 int parse_pid(const char *s, pid_t* ret_pid) {
         unsigned long ul = 0;
         pid_t pid;
         int r;
 
         assert(s);
-        assert(ret_pid);
 
         r = safe_atolu(s, &ul);
         if (r < 0)
@@ -64,7 +81,8 @@ int parse_pid(const char *s, pid_t* ret_pid) {
         if (!pid_is_valid(pid))
                 return -ERANGE;
 
-        *ret_pid = pid;
+        if (ret_pid)
+                *ret_pid = pid;
         return 0;
 }
 
@@ -105,8 +123,7 @@ int parse_ifindex(const char *s) {
 }
 
 int parse_mtu(int family, const char *s, uint32_t *ret) {
-        uint64_t u;
-        size_t m;
+        uint64_t u, m;
         int r;
 
         r = parse_size(s, 1024, &u);
@@ -116,10 +133,16 @@ int parse_mtu(int family, const char *s, uint32_t *ret) {
         if (u > UINT32_MAX)
                 return -ERANGE;
 
-        if (family == AF_INET6)
+        switch (family) {
+        case AF_INET:
+                m = IPV4_MIN_MTU; /* This is 68 */
+                break;
+        case 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 */
+                break;
+        default:
+                m = 0;
+        }
 
         if (u < m)
                 return -ERANGE;
@@ -256,6 +279,26 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
         return 0;
 }
 
+int parse_sector_size(const char *t, uint64_t *ret) {
+        int r;
+
+        assert(t);
+        assert(ret);
+
+        uint64_t ss;
+
+        r = safe_atou64(t, &ss);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse sector size parameter %s", t);
+        if (ss < 512 || ss > 4096) /* Allow up to 4K due to dm-crypt support and 4K alignment by the homed LUKS backend */
+                return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Sector size not between 512 and 4096: %s", t);
+        if (!ISPOWEROF2(ss))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Sector size not power of 2: %s", t);
+
+        *ret = ss;
+        return 0;
+}
+
 int parse_range(const char *t, unsigned *lower, unsigned *upper) {
         _cleanup_free_ char *word = NULL;
         unsigned l, u;
@@ -313,6 +356,21 @@ int parse_errno(const char *t) {
         return e;
 }
 
+int parse_fd(const char *t) {
+        int r, fd;
+
+        assert(t);
+
+        r = safe_atoi(t, &fd);
+        if (r < 0)
+                return r;
+
+        if (fd < 0)
+                return -EBADF;
+
+        return fd;
+}
+
 static const char *mangle_base(const char *s, unsigned *base) {
         const char *k;
 
@@ -390,6 +448,21 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
         return 0;
 }
 
+int safe_atou_bounded(const char *s, unsigned min, unsigned max, unsigned *ret) {
+        unsigned v;
+        int r;
+
+        r = safe_atou(s, &v);
+        if (r < 0)
+                return r;
+
+        if (v < min || v > max)
+                return -ERANGE;
+
+        *ret = v;
+        return 0;
+}
+
 int safe_atoi(const char *s, int *ret_i) {
         unsigned base = 0;
         char *x = NULL;
@@ -476,69 +549,31 @@ int safe_atolli(const char *s, long long int *ret_lli) {
         return 0;
 }
 
-int safe_atou8(const char *s, uint8_t *ret) {
-        unsigned base = 0;
-        unsigned long l;
-        char *x = NULL;
-
-        assert(s);
-
-        s += strspn(s, WHITESPACE);
-        s = mangle_base(s, &base);
+int safe_atou8_full(const char *s, unsigned base, uint8_t *ret) {
+        unsigned u;
+        int r;
 
-        errno = 0;
-        l = strtoul(s, &x, base);
-        if (errno > 0)
-                return -errno;
-        if (!x || x == s || *x != 0)
-                return -EINVAL;
-        if (l != 0 && s[0] == '-')
-                return -ERANGE;
-        if ((unsigned long) (uint8_t) l != l)
+        r = safe_atou_full(s, base, &u);
+        if (r < 0)
+                return r;
+        if (u > UINT8_MAX)
                 return -ERANGE;
 
-        if (ret)
-                *ret = (uint8_t) l;
+        *ret = (uint8_t) u;
         return 0;
 }
 
 int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
-        char *x = NULL;
-        unsigned long l;
-
-        assert(s);
-        assert(SAFE_ATO_MASK_FLAGS(base) <= 16);
-
-        if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_WHITESPACE) &&
-            strchr(WHITESPACE, s[0]))
-                return -EINVAL;
-
-        s += strspn(s, WHITESPACE);
-
-        if (FLAGS_SET(base, SAFE_ATO_REFUSE_PLUS_MINUS) &&
-            IN_SET(s[0], '+', '-'))
-                return -EINVAL;
-
-        if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_ZERO) &&
-            s[0] == '0' && s[1] != 0)
-                return -EINVAL;
-
-        s = mangle_base(s, &base);
+        unsigned u;
+        int r;
 
-        errno = 0;
-        l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base));
-        if (errno > 0)
-                return -errno;
-        if (!x || x == s || *x != 0)
-                return -EINVAL;
-        if (l != 0 && s[0] == '-')
-                return -ERANGE;
-        if ((unsigned long) (uint16_t) l != l)
+        r = safe_atou_full(s, base, &u);
+        if (r < 0)
+                return r;
+        if (u > UINT16_MAX)
                 return -ERANGE;
 
-        if (ret)
-                *ret = (uint16_t) l;
-
+        *ret = (uint16_t) u;
         return 0;
 }
 
@@ -750,3 +785,22 @@ int parse_loadavg_fixed_point(const char *s, loadavg_t *ret) {
 
         return store_loadavg_fixed_point(i, f, ret);
 }
+
+/* Limitations are described in https://www.netfilter.org/projects/nftables/manpage.html and
+ * https://bugzilla.netfilter.org/show_bug.cgi?id=1175 */
+bool nft_identifier_valid(const char *id) {
+        if (!id)
+                return false;
+
+        size_t len = strlen(id);
+        if (len == 0 || len > 31)
+                return false;
+
+        if (!ascii_isalpha(id[0]))
+                return false;
+
+        for (size_t i = 1; i < len; i++)
+                if (!ascii_isalpha(id[i]) && !ascii_isdigit(id[i]) && !IN_SET(id[i], '/', '\\', '_', '.'))
+                        return false;
+        return true;
+}