chiark / gitweb /
core: add "invocation ID" concept to service manager
[elogind.git] / src / libelogind / sd-id128 / sd-id128.c
index 46f2181ea809504b3126819fec1fd8c8d30814b3..d4450c70a003c357b0dafce92a542e2f67f87459 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "util.h"
-#include "macro.h"
 #include "sd-id128.h"
+
+#include "fd-util.h"
+#include "hexdecoct.h"
+#include "id128-util.h"
+#include "io-util.h"
+#include "macro.h"
 #include "random-util.h"
+#include "util.h"
 
-_public_ char *sd_id128_to_string(sd_id128_t id, char s[33]) {
+_public_ char *sd_id128_to_string(sd_id128_t id, char s[SD_ID128_STRING_MAX]) {
         unsigned n;
 
         assert_return(s, NULL);
@@ -49,7 +52,6 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
         bool is_guid = false;
 
         assert_return(s, -EINVAL);
-        assert_return(ret, -EINVAL);
 
         for (n = 0, i = 0; n < 16;) {
                 int a, b;
@@ -87,121 +89,79 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
         if (s[i] != 0)
                 return -EINVAL;
 
-        *ret = t;
+        if (ret)
+                *ret = t;
         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;
+        *ret = saved_boot_id;
+        return 0;
+}
 
-        r = loop_read_exact(fd, buf, 36, false);
-        if (r < 0)
-                return r;
+_public_ int sd_id128_get_invocation(sd_id128_t *ret) {
+        static thread_local sd_id128_t saved_invocation_id = {};
+        int r;
 
-        for (j = 0, p = buf; j < 16; j++) {
-                int a, b;
+        assert_return(ret, -EINVAL);
 
-                if (p >= buf + 35)
-                        return -EIO;
+        if (sd_id128_is_null(saved_invocation_id)) {
+                const char *e;
 
-                if (*p == '-') {
-                        p++;
-                        if (p >= buf + 35)
-                                return -EIO;
-                }
+                e = secure_getenv("INVOCATION_ID");
+                if (!e)
+                        return -ENXIO;
 
-                a = unhexchar(p[0]);
-                b = unhexchar(p[1]);
+                r = sd_id128_from_string(e, &saved_invocation_id);
+                if (r < 0)
+                        return r;
+        }
 
-                if (a < 0 || b < 0)
-                        return -EIO;
+        *ret = saved_invocation_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) {