]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/sd-id128.c
systemctl: don't show ln -s/rm output in 'install' mode if --quiet is passed
[thirdparty/systemd.git] / src / sd-id128.c
CommitLineData
87d2c1ff
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
23#include <fcntl.h>
24#include <unistd.h>
25
26#include "sd-id128.h"
81527be1 27
87d2c1ff
LP
28#include "util.h"
29#include "macro.h"
30
000a2c98 31_public_ char *sd_id128_to_string(sd_id128_t id, char s[33]) {
87d2c1ff
LP
32 unsigned n;
33
000a2c98
LP
34 if (!s)
35 return NULL;
87d2c1ff
LP
36
37 for (n = 0; n < 16; n++) {
38 s[n*2] = hexchar(id.bytes[n] >> 4);
39 s[n*2+1] = hexchar(id.bytes[n] & 0xF);
40 }
41
42 s[32] = 0;
43
44 return s;
45}
46
000a2c98 47_public_ int sd_id128_from_string(const char s[33], sd_id128_t *ret) {
87d2c1ff
LP
48 unsigned n;
49 sd_id128_t t;
50
000a2c98
LP
51 if (!s)
52 return -EINVAL;
53 if (!ret)
54 return -EINVAL;
87d2c1ff
LP
55
56 for (n = 0; n < 16; n++) {
57 int a, b;
58
59 a = unhexchar(s[n*2]);
60 if (a < 0)
61 return -EINVAL;
62
63 b = unhexchar(s[n*2+1]);
64 if (b < 0)
65 return -EINVAL;
66
67 t.bytes[n] = (a << 4) | b;
68 }
69
70 if (s[32] != 0)
71 return -EINVAL;
72
73 *ret = t;
74 return 0;
75}
76
e4bac488 77static sd_id128_t make_v4_uuid(sd_id128_t id) {
87d2c1ff
LP
78 /* Stolen from generate_random_uuid() of drivers/char/random.c
79 * in the kernel sources */
80
81 /* Set UUID version to 4 --- truly random generation */
82 id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
83
84 /* Set the UUID variant to DCE */
85 id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
86
87 return id;
88}
89
000a2c98 90_public_ int sd_id128_get_machine(sd_id128_t *ret) {
87d2c1ff
LP
91 static __thread sd_id128_t saved_machine_id;
92 static __thread bool saved_machine_id_valid = false;
93 int fd;
94 char buf[32];
95 ssize_t k;
96 unsigned j;
97 sd_id128_t t;
98
000a2c98
LP
99 if (!ret)
100 return -EINVAL;
101
87d2c1ff
LP
102 if (saved_machine_id_valid) {
103 *ret = saved_machine_id;
104 return 0;
105 }
106
107 fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
108 if (fd < 0)
109 return -errno;
110
111 k = loop_read(fd, buf, 32, false);
112 close_nointr_nofail(fd);
113
114 if (k < 0)
115 return (int) k;
116
117 if (k < 32)
118 return -EIO;
119
120 for (j = 0; j < 16; j++) {
121 int a, b;
122
123 a = unhexchar(buf[j*2]);
124 b = unhexchar(buf[j*2+1]);
125
126 if (a < 0 || b < 0)
127 return -EIO;
128
129 t.bytes[j] = a << 4 | b;
130 }
131
132 saved_machine_id = t;
133 saved_machine_id_valid = true;
134
135 *ret = t;
136 return 0;
137}
138
000a2c98 139_public_ int sd_id128_get_boot(sd_id128_t *ret) {
87d2c1ff
LP
140 static __thread sd_id128_t saved_boot_id;
141 static __thread bool saved_boot_id_valid = false;
142 int fd;
143 char buf[36];
144 ssize_t k;
145 unsigned j;
146 sd_id128_t t;
147 char *p;
148
000a2c98
LP
149 if (!ret)
150 return -EINVAL;
151
87d2c1ff
LP
152 if (saved_boot_id_valid) {
153 *ret = saved_boot_id;
154 return 0;
155 }
156
157 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
158 if (fd < 0)
159 return -errno;
160
161 k = loop_read(fd, buf, 36, false);
162 close_nointr_nofail(fd);
163
164 if (k < 0)
165 return (int) k;
166
167 if (k < 36)
168 return -EIO;
169
170 for (j = 0, p = buf; j < 16; j++) {
171 int a, b;
172
173 if (*p == '-')
174 p++;
175
176 a = unhexchar(p[0]);
177 b = unhexchar(p[1]);
178
179 if (a < 0 || b < 0)
180 return -EIO;
181
182 t.bytes[j] = a << 4 | b;
183
184 p += 2;
185 }
186
187 saved_boot_id = t;
188 saved_boot_id_valid = true;
189
190 *ret = t;
191 return 0;
192}
193
000a2c98 194_public_ int sd_id128_randomize(sd_id128_t *ret) {
87d2c1ff
LP
195 int fd;
196 ssize_t k;
197 sd_id128_t t;
198
000a2c98
LP
199 if (!ret)
200 return -EINVAL;
87d2c1ff
LP
201
202 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
203 if (fd < 0)
204 return -errno;
205
206 k = loop_read(fd, &t, 16, false);
207 close_nointr_nofail(fd);
208
209 if (k < 0)
210 return (int) k;
211
212 if (k < 16)
213 return -EIO;
214
215 /* Turn this into a valid v4 UUID, to be nice. Note that we
216 * only guarantee this for newly generated UUIDs, not for
217 * pre-existing ones.*/
218
e4bac488 219 *ret = make_v4_uuid(t);
87d2c1ff
LP
220 return 0;
221}