]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-id128: split UUID file read/write code into new id128-util.[ch]
authorLennart Poettering <lennart@poettering.net>
Thu, 21 Jul 2016 15:57:57 +0000 (17:57 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 22 Jul 2016 10:59:36 +0000 (12:59 +0200)
We currently have code to read and write files containing UUIDs at various
places. Unify this in id128-util.[ch], and move some other stuff there too.

The new files are located in src/libsystemd/sd-id128/ (instead of src/shared/),
because they are actually the backend of sd_id128_get_machine() and
sd_id128_get_boot().

In follow-up patches we can use this reduce the code in nspawn and
machine-id-setup by adopted the common implementation.

Makefile.am
src/basic/util.c
src/basic/util.h
src/core/machine-id-setup.c
src/libsystemd/sd-id128/id128-util.c [new file with mode: 0644]
src/libsystemd/sd-id128/id128-util.h [new file with mode: 0644]
src/libsystemd/sd-id128/sd-id128.c
src/nspawn/nspawn.c
src/test/test-id128.c

index c9fb4917ad43219f6311aa7d099d5e0888408420..f7288f6df7f346a187e7e0c2b6c213c7378b0147 100644 (file)
@@ -242,6 +242,7 @@ AM_CPPFLAGS = \
        -I $(top_srcdir)/src/libsystemd/sd-network \
        -I $(top_srcdir)/src/libsystemd/sd-hwdb \
        -I $(top_srcdir)/src/libsystemd/sd-device \
+       -I $(top_srcdir)/src/libsystemd/sd-id128 \
        -I $(top_srcdir)/src/libsystemd-network \
        $(OUR_CPPFLAGS)
 
@@ -3213,6 +3214,8 @@ libsystemd_internal_la_SOURCES = \
        src/libsystemd/sd-netlink/local-addresses.h \
        src/libsystemd/sd-netlink/local-addresses.c \
        src/libsystemd/sd-id128/sd-id128.c \
+       src/libsystemd/sd-id128/id128-util.h \
+       src/libsystemd/sd-id128/id128-util.c \
        src/libsystemd/sd-daemon/sd-daemon.c \
        src/libsystemd/sd-login/sd-login.c \
        src/libsystemd/sd-path/sd-path.c \
index 09d16697b70263e9e713206866304e2fa5e8ae93..41e79315ae7760e6e83915ba34ac0ac11da97a3a 100644 (file)
@@ -581,47 +581,6 @@ int on_ac_power(void) {
         return found_online || !found_offline;
 }
 
-bool id128_is_valid(const char *s) {
-        size_t i, l;
-
-        l = strlen(s);
-        if (l == 32) {
-
-                /* Simple formatted 128bit hex string */
-
-                for (i = 0; i < l; i++) {
-                        char c = s[i];
-
-                        if (!(c >= '0' && c <= '9') &&
-                            !(c >= 'a' && c <= 'z') &&
-                            !(c >= 'A' && c <= 'Z'))
-                                return false;
-                }
-
-        } else if (l == 36) {
-
-                /* Formatted UUID */
-
-                for (i = 0; i < l; i++) {
-                        char c = s[i];
-
-                        if ((i == 8 || i == 13 || i == 18 || i == 23)) {
-                                if (c != '-')
-                                        return false;
-                        } else {
-                                if (!(c >= '0' && c <= '9') &&
-                                    !(c >= 'a' && c <= 'z') &&
-                                    !(c >= 'A' && c <= 'Z'))
-                                        return false;
-                        }
-                }
-
-        } else
-                return false;
-
-        return true;
-}
-
 int container_get_leader(const char *machine, pid_t *pid) {
         _cleanup_free_ char *s = NULL, *class = NULL;
         const char *p;
index db105197e8466ad1b3405655e630e7a50b3ad151..94b80919061514ec5b19cbd3b824599e7986535d 100644 (file)
@@ -176,8 +176,6 @@ static inline unsigned log2u_round_up(unsigned x) {
         return log2u(x - 1) + 1;
 }
 
-bool id128_is_valid(const char *s) _pure_;
-
 int container_get_leader(const char *machine, pid_t *pid);
 
 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
index ea6b085e4f5ef00b39af05fddd571494dda1cd03..62f80833ddf9fcba35b7b94de9c1769f6606d7ef 100644 (file)
@@ -32,6 +32,7 @@
 #include "fileio.h"
 #include "fs-util.h"
 #include "hexdecoct.h"
+#include "id128-util.h"
 #include "io-util.h"
 #include "log.h"
 #include "machine-id-setup.h"
diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c
new file mode 100644 (file)
index 0000000..c1742ca
--- /dev/null
@@ -0,0 +1,171 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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/>.
+***/
+
+#include <fcntl.h>
+
+#include "fd-util.h"
+#include "hexdecoct.h"
+#include "id128-util.h"
+#include "io-util.h"
+#include "stdio-util.h"
+
+char *id128_to_uuid_string(sd_id128_t id, char s[37]) {
+        unsigned n, k = 0;
+
+        assert(s);
+
+        /* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
+
+        for (n = 0; n < 16; n++) {
+
+                if (IN_SET(n, 4, 6, 8, 10))
+                        s[k++] = '-';
+
+                s[k++] = hexchar(id.bytes[n] >> 4);
+                s[k++] = hexchar(id.bytes[n] & 0xF);
+        }
+
+        assert(k == 36);
+
+        s[k] = 0;
+
+        return s;
+}
+
+bool id128_is_valid(const char *s) {
+        size_t i, l;
+
+        assert(s);
+
+        l = strlen(s);
+        if (l == 32) {
+
+                /* Plain formatted 128bit hex string */
+
+                for (i = 0; i < l; i++) {
+                        char c = s[i];
+
+                        if (!(c >= '0' && c <= '9') &&
+                            !(c >= 'a' && c <= 'z') &&
+                            !(c >= 'A' && c <= 'Z'))
+                                return false;
+                }
+
+        } else if (l == 36) {
+
+                /* Formatted UUID */
+
+                for (i = 0; i < l; i++) {
+                        char c = s[i];
+
+                        if ((i == 8 || i == 13 || i == 18 || i == 23)) {
+                                if (c != '-')
+                                        return false;
+                        } else {
+                                if (!(c >= '0' && c <= '9') &&
+                                    !(c >= 'a' && c <= 'z') &&
+                                    !(c >= 'A' && c <= 'Z'))
+                                        return false;
+                        }
+                }
+
+        } else
+                return false;
+
+        return true;
+}
+
+int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
+        char buffer[36 + 2];
+        ssize_t l;
+
+        assert(fd >= 0);
+        assert(f < _ID128_FORMAT_MAX);
+
+        /* Reads an 128bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both
+         * followed by a newline and nothing else. */
+
+        l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 33 or 37 chars */
+        if (l < 0)
+                return (int) l;
+        if (l == 0) /* empty? */
+                return -ENOMEDIUM;
+
+        if (l == 33) {
+                if (f == ID128_UUID)
+                        return -EINVAL;
+
+                if (buffer[32] != '\n')
+                        return -EINVAL;
+
+                buffer[32] = 0;
+
+        } else if (l == 37) {
+                if (f == ID128_PLAIN)
+                        return -EINVAL;
+
+                if (buffer[36] != '\n')
+                        return -EINVAL;
+
+                buffer[36] = 0;
+        } else
+                return -EINVAL;
+
+        return sd_id128_from_string(buffer, ret);
+}
+
+int id128_read(const char *p, Id128Format f, sd_id128_t *ret) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+        if (fd < 0)
+                return -errno;
+
+        return id128_read_fd(fd, f, ret);
+}
+
+int id128_write_fd(int fd, Id128Format f, sd_id128_t id) {
+        char buffer[36 + 2];
+        size_t sz;
+
+        assert(fd >= 0);
+        assert(f < _ID128_FORMAT_MAX);
+
+        if (f != ID128_UUID) {
+                sd_id128_to_string(id, buffer);
+                buffer[32] = '\n';
+                sz = 33;
+        } else {
+                id128_to_uuid_string(id, buffer);
+                buffer[36] = '\n';
+                sz = 37;
+        }
+
+        return loop_write(fd, buffer, sz, false);
+}
+
+int id128_write(const char *p, Id128Format f, sd_id128_t id) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444);
+        if (fd < 0)
+                return -errno;
+
+        return id128_write_fd(fd, f, id);
+}
diff --git a/src/libsystemd/sd-id128/id128-util.h b/src/libsystemd/sd-id128/id128-util.h
new file mode 100644 (file)
index 0000000..73e4c71
--- /dev/null
@@ -0,0 +1,45 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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/>.
+***/
+
+#include <stdbool.h>
+
+#include "sd-id128.h"
+#include "macro.h"
+
+char *id128_to_uuid_string(sd_id128_t id, char s[37]);
+
+/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format */
+#define ID128_UUID_FORMAT_STR "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+
+bool id128_is_valid(const char *s) _pure_;
+
+typedef enum Id128Format {
+        ID128_ANY,
+        ID128_PLAIN,  /* formatted as 32 hex chars as-is */
+        ID128_UUID,   /* formatted as 36 character uuid string */
+        _ID128_FORMAT_MAX,
+} Id128Format;
+
+int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret);
+int id128_read(const char *p, Id128Format f, sd_id128_t *ret);
+
+int id128_write_fd(int fd, Id128Format f, sd_id128_t id);
+int id128_write(const char *p, Id128Format f, sd_id128_t id);
index d9c0116f60a53373428b6534113f3fc3693df6fe..1470e4c01a7f9c71d365c115d141f084b6a3fdb0 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "fd-util.h"
 #include "hexdecoct.h"
+#include "id128-util.h"
 #include "io-util.h"
 #include "macro.h"
 #include "random-util.h"
@@ -93,117 +94,52 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
         return 0;
 }
 
-static sd_id128_t make_v4_uuid(sd_id128_t id) {
-        /* Stolen from generate_random_uuid() of drivers/char/random.c
-         * in the kernel sources */
-
-        /* Set UUID version to 4 --- truly random generation */
-        id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
-
-        /* Set the UUID variant to DCE */
-        id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
-
-        return id;
-}
-
 _public_ int sd_id128_get_machine(sd_id128_t *ret) {
-        static thread_local sd_id128_t saved_machine_id;
-        static thread_local bool saved_machine_id_valid = false;
-        _cleanup_close_ int fd = -1;
-        char buf[33];
-        unsigned j;
-        sd_id128_t t;
+        static thread_local sd_id128_t saved_machine_id = {};
         int r;
 
         assert_return(ret, -EINVAL);
 
-        if (saved_machine_id_valid) {
-                *ret = saved_machine_id;
-                return 0;
-        }
-
-        fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
-        if (fd < 0)
-                return -errno;
-
-        r = loop_read_exact(fd, buf, 33, false);
-        if (r < 0)
-                return r;
-        if (buf[32] !='\n')
-                return -EIO;
-
-        for (j = 0; j < 16; j++) {
-                int a, b;
-
-                a = unhexchar(buf[j*2]);
-                b = unhexchar(buf[j*2+1]);
+        if (sd_id128_is_null(saved_machine_id)) {
+                r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id);
+                if (r < 0)
+                        return r;
 
-                if (a < 0 || b < 0)
-                        return -EIO;
-
-                t.bytes[j] = a << 4 | b;
+                if (sd_id128_is_null(saved_machine_id))
+                        return -EINVAL;
         }
 
-        saved_machine_id = t;
-        saved_machine_id_valid = true;
-
-        *ret = t;
+        *ret = saved_machine_id;
         return 0;
 }
 
 _public_ int sd_id128_get_boot(sd_id128_t *ret) {
-        static thread_local sd_id128_t saved_boot_id;
-        static thread_local bool saved_boot_id_valid = false;
-        _cleanup_close_ int fd = -1;
-        char buf[36];
-        unsigned j;
-        sd_id128_t t;
-        char *p;
+        static thread_local sd_id128_t saved_boot_id = {};
         int r;
 
         assert_return(ret, -EINVAL);
 
-        if (saved_boot_id_valid) {
-                *ret = saved_boot_id;
-                return 0;
+        if (sd_id128_is_null(saved_boot_id)) {
+                r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id);
+                if (r < 0)
+                        return r;
         }
 
-        fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
-        if (fd < 0)
-                return -errno;
-
-        r = loop_read_exact(fd, buf, 36, false);
-        if (r < 0)
-                return r;
-
-        for (j = 0, p = buf; j < 16; j++) {
-                int a, b;
-
-                if (p >= buf + 35)
-                        return -EIO;
-
-                if (*p == '-') {
-                        p++;
-                        if (p >= buf + 35)
-                                return -EIO;
-                }
-
-                a = unhexchar(p[0]);
-                b = unhexchar(p[1]);
-
-                if (a < 0 || b < 0)
-                        return -EIO;
+        *ret = saved_boot_id;
+        return 0;
+}
 
-                t.bytes[j] = a << 4 | b;
+static sd_id128_t make_v4_uuid(sd_id128_t id) {
+        /* Stolen from generate_random_uuid() of drivers/char/random.c
+         * in the kernel sources */
 
-                p += 2;
-        }
+        /* Set UUID version to 4 --- truly random generation */
+        id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
 
-        saved_boot_id = t;
-        saved_boot_id_valid = true;
+        /* Set the UUID variant to DCE */
+        id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
 
-        *ret = t;
-        return 0;
+        return id;
 }
 
 _public_ int sd_id128_randomize(sd_id128_t *ret) {
index ae0d2a8deb981fae9bfef092e2f792bb21bc2850..d9301bd4dc922f2fc35450da4e8fe04922510cb4 100644 (file)
@@ -61,6 +61,7 @@
 #include "fs-util.h"
 #include "gpt.h"
 #include "hostname-util.h"
+#include "id128-util.h"
 #include "log.h"
 #include "loopback-setup.h"
 #include "machine-id-setup.h"
 #include "nspawn-network.h"
 #include "nspawn-patch-uid.h"
 #include "nspawn-register.h"
+#include "nspawn-seccomp.h"
 #include "nspawn-settings.h"
 #include "nspawn-setuid.h"
 #include "nspawn-stub-pid1.h"
-#include "nspawn-seccomp.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
index 96aa008c06ed49c2aea669c266aba90c09947c4e..324c7a201978bf60348221f05bc6c02ee1f523a9 100644 (file)
@@ -26,6 +26,7 @@
 #include "macro.h"
 #include "string-util.h"
 #include "util.h"
+#include "id128-util.h"
 
 #define ID128_WALDI SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10)
 #define STR_WALDI "0102030405060708090a0b0c0d0e0f10"
@@ -33,7 +34,7 @@
 
 int main(int argc, char *argv[]) {
         sd_id128_t id, id2;
-        char t[33];
+        char t[33], q[37];
         _cleanup_free_ char *b = NULL;
 
         assert_se(sd_id128_randomize(&id) == 0);
@@ -57,6 +58,17 @@ int main(int argc, char *argv[]) {
         printf("waldi2: %s\n", b);
         assert_se(streq(t, b));
 
+        printf("waldi3: %s\n", id128_to_uuid_string(ID128_WALDI, q));
+        assert_se(streq(q, UUID_WALDI));
+
+        b = mfree(b);
+        assert_se(asprintf(&b, ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 36);
+        printf("waldi4: %s\n", b);
+        assert_se(streq(q, b));
+
+        assert_se(sd_id128_from_string(STR_WALDI, &id) >= 0);
+        assert_se(sd_id128_equal(id, ID128_WALDI));
+
         assert_se(sd_id128_from_string(UUID_WALDI, &id) >= 0);
         assert_se(sd_id128_equal(id, ID128_WALDI));