1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
|
'\" t
.TH "SD\-ID128" "3" "" "systemd 256~rc3" "sd-id128"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
sd-id128, SD_ID128_ALLF, SD_ID128_CONST_STR, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL, SD_ID128_MAKE, SD_ID128_MAKE_STR, SD_ID128_MAKE_UUID_STR, SD_ID128_NULL, SD_ID128_UUID_FORMAT_STR, sd_id128_equal, sd_id128_string_equal, sd_id128_in_set, sd_id128_in_set_sentinel, sd_id128_in_setv, sd_id128_is_allf, sd_id128_is_null, sd_id128_t \- APIs for processing 128\-bit IDs
.SH "SYNOPSIS"
.sp
.ft B
.nf
#include <systemd/sd\-id128\&.h>
.fi
.ft
.PP
\fBSD_ID128_ALLF\fR
.PP
\fBSD_ID128_NULL\fR
.PP
\fBSD_ID128_CONST_STR(\fR\fB\fIid\fR\fR\fB)\fR
.PP
\fBSD_ID128_FORMAT_STR\fR
.PP
\fBSD_ID128_FORMAT_VAL(\fR\fB\fIid\fR\fR\fB)\fR
.PP
\fBSD_ID128_MAKE(\fR\fB\fIv0\fR\fR\fB, \fR\fB\fIv1\fR\fR\fB, \fR\fB\fIv2\fR\fR\fB, \fR\fB\fIv3\fR\fR\fB, \fR\fB\fIv4\fR\fR\fB, \fR\fB\fIv5\fR\fR\fB, \fR\fB\fIv6\fR\fR\fB, \fR\fB\fIv7\fR\fR\fB, \fR\fB\fIv8\fR\fR\fB, \fR\fB\fIv9\fR\fR\fB, \fR\fB\fIvA\fR\fR\fB, \fR\fB\fIvB\fR\fR\fB, \fR\fB\fIvC\fR\fR\fB, \fR\fB\fIvD\fR\fR\fB, \fR\fB\fIvE\fR\fR\fB, \fR\fB\fIvF\fR\fR\fB)\fR
.PP
\fBSD_ID128_MAKE_STR(\fR\fB\fIv0\fR\fR\fB, \fR\fB\fIv1\fR\fR\fB, \fR\fB\fIv2\fR\fR\fB, \fR\fB\fIv3\fR\fR\fB, \fR\fB\fIv4\fR\fR\fB, \fR\fB\fIv5\fR\fR\fB, \fR\fB\fIv6\fR\fR\fB, \fR\fB\fIv7\fR\fR\fB, \fR\fB\fIv8\fR\fR\fB, \fR\fB\fIv9\fR\fR\fB, \fR\fB\fIvA\fR\fR\fB, \fR\fB\fIvB\fR\fR\fB, \fR\fB\fIvC\fR\fR\fB, \fR\fB\fIvD\fR\fR\fB, \fR\fB\fIvE\fR\fR\fB, \fR\fB\fIvF\fR\fR\fB)\fR
.PP
\fBSD_ID128_MAKE_UUID_STR(\fR\fB\fIv0\fR\fR\fB, \fR\fB\fIv1\fR\fR\fB, \fR\fB\fIv2\fR\fR\fB, \fR\fB\fIv3\fR\fR\fB, \fR\fB\fIv4\fR\fR\fB, \fR\fB\fIv5\fR\fR\fB, \fR\fB\fIv6\fR\fR\fB, \fR\fB\fIv7\fR\fR\fB, \fR\fB\fIv8\fR\fR\fB, \fR\fB\fIv9\fR\fR\fB, \fR\fB\fIvA\fR\fR\fB, \fR\fB\fIvB\fR\fR\fB, \fR\fB\fIvC\fR\fR\fB, \fR\fB\fIvD\fR\fR\fB, \fR\fB\fIvE\fR\fR\fB, \fR\fB\fIvF\fR\fR\fB)\fR
.PP
\fBSD_ID128_UUID_FORMAT_STR\fR
.HP \w'int\ sd_id128_equal('u
.BI "int sd_id128_equal(sd_id128_t\ " "a" ", sd_id128_t\ " "b" ");"
.HP \w'int\ sd_id128_string_equal('u
.BI "int sd_id128_string_equal(const\ char\ *" "a" ", sd_id128_t\ " "b" ");"
.HP \w'int\ sd_id128_is_null('u
.BI "int sd_id128_is_null(sd_id128_t\ " "id" ");"
.HP \w'int\ sd_id128_is_allf('u
.BI "int sd_id128_is_allf(sd_id128_t\ " "id" ");"
.HP \w'int\ sd_id128_in_setv('u
.BI "int sd_id128_in_setv(sd_id128_t\ " "id" ", va_list\ " "ap" ");"
.HP \w'int\ sd_id128_in_set_sentinel('u
.BI "int sd_id128_in_set_sentinel(sd_id128_t\ " "id" ", \&..., " "\fBSD_ID128_NULL\fR" ");"
.HP \w'int\ sd_id128_in_set('u
.BI "int sd_id128_in_set(sd_id128_t\ " "id" ", \&...);"
.HP \w'\fBpkg\-config\ \-\-cflags\ \-\-libs\ libsystemd\fR\ 'u
\fBpkg\-config \-\-cflags \-\-libs libsystemd\fR
.SH "DESCRIPTION"
.PP
sd\-id128\&.h
is part of
\fBlibsystemd\fR(3)
and provides APIs to generate, convert, and compare 128\-bit ID values\&. The 128\-bit ID values processed and generated by these APIs are a generalization of OSF UUIDs as defined by
\m[blue]\fBRFC 4122\fR\m[]\&\s-2\u[1]\d\s+2
but use a simpler string format\&. These functions impose no structure on the used IDs, much unlike OSF UUIDs or Microsoft GUIDs, but are mostly compatible with those types of IDs\&.
.PP
A 128\-bit ID is implemented as the following union type:
.sp
.if n \{\
.RS 4
.\}
.nf
typedef union sd_id128 {
uint8_t bytes[16];
uint64_t qwords[2];
} sd_id128_t;
.fi
.if n \{\
.RE
.\}
.PP
This union type allows accessing the 128\-bit ID as 16 separate bytes or two 64\-bit words\&. It is generally safer to access the ID components by their 8\-bit array to avoid endianness issues\&. This union is intended to be passed by value (as opposed to pass\-by\-reference) and may be directly manipulated by clients\&.
.PP
A couple of macros are defined to denote and decode 128\-bit IDs:
.PP
\fBSD_ID128_MAKE()\fR
is used to write a constant ID in source code\&. A commonly used idiom is to assign a name to an ID using this macro:
.sp
.if n \{\
.RS 4
.\}
.nf
#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)
.fi
.if n \{\
.RE
.\}
.PP
\fBSD_ID128_NULL\fR
defines an ID consisting of only
\fBNUL\fR
bytes (i\&.e\&. all bits off)\&.
.PP
\fBSD_ID128_ALLF\fR
defines an ID consisting of only
\fB0xFF\fR
bytes (i\&.e\&. all bits on)\&.
.PP
\fBSD_ID128_MAKE_STR()\fR
is similar to
\fBSD_ID128_MAKE()\fR, but creates a
\fBconst char*\fR
expression that can be conveniently used in message formats and such:
.sp
.if n \{\
.RS 4
.\}
.nf
#include <stdio\&.h>
#define SD_MESSAGE_COREDUMP_STR SD_ID128_MAKE_STR(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)
int main(int argc, char **argv) {
puts("Match for coredumps: MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR);
}
.fi
.if n \{\
.RE
.\}
.PP
\fBSD_ID128_CONST_STR()\fR
converts constant IDs into constant strings for output\&. The following example code will output the string "fc2e22bc6ee647b6b90729ab34a250b1":
.sp
.if n \{\
.RS 4
.\}
.nf
int main(int argc, char *argv[]) {
puts("Match for coredumps: %s", SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP));
}
.fi
.if n \{\
.RE
.\}
.PP
\fBSD_ID128_FORMAT_STR\fR
and
\fBSD_ID128_FORMAT_VAL()\fR
is used to format an ID in a
\fBprintf\fR(3)
format string, as shown in the following example:
.sp
.if n \{\
.RS 4
.\}
.nf
int main(int argc, char *argv[]) {
sd_id128_t id;
id = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
printf("The ID encoded in this C file is " SD_ID128_FORMAT_STR "\&.\en", SD_ID128_FORMAT_VAL(id));
return 0;
}
.fi
.if n \{\
.RE
.\}
.PP
\fBSD_ID128_UUID_FORMAT_STR\fR
and
\fBSD_ID128_MAKE_UUID_STR()\fR
are similar to
\fBSD_ID128_FORMAT_STR\fR
and
\fBSD_ID128_MAKE_STR()\fR, but include separating hyphens to conform to the "\m[blue]\fBUUID canonical representation\fR\m[]\&\s-2\u[2]\d\s+2"\&. They format the string based on
\m[blue]\fBRFC4122\fR\m[]\&\s-2\u[1]\d\s+2
Variant 1 rules, i\&.e\&. converting from Big Endian byte order\&. This matches behaviour of most other Linux userspace infrastructure\&. It\*(Aqs probably best to avoid UUIDs of other variants, in order to avoid unnecessary ambiguities\&. All 128\-bit IDs generated by the sd\-id128 APIs strictly conform to Variant 1 Version 4 UUIDs, as per RFC 4122\&.
.PP
\fBsd_id128_equal()\fR
compares two 128\-bit IDs:
.sp
.if n \{\
.RS 4
.\}
.nf
int main(int argc, char *argv[]) {
sd_id128_t a, b, c;
a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
b = SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e);
c = a;
assert(sd_id128_equal(a, c));
assert(!sd_id128_equal(a, b));
return 0;
}
.fi
.if n \{\
.RE
.\}
.PP
\fBsd_id128_string_equal()\fR
is similar to
\fBsd_id128_equal()\fR, but the first ID is formatted as
\fBconst char*\fR\&. The same restrictions apply as to the first argument of
\fBsd_id128_from_string()\fR\&.
.PP
\fBsd_id128_is_null()\fR
checks if an ID consists of only
\fBNUL\fR
bytes:
.sp
.if n \{\
.RS 4
.\}
.nf
assert(sd_id128_is_null(SD_ID128_NULL));
.fi
.if n \{\
.RE
.\}
.PP
Similarly,
\fBsd_id128_is_allf()\fR
checks if an ID consists of only
\fB0xFF\fR
bytes (all bits on):
.sp
.if n \{\
.RS 4
.\}
.nf
assert(sd_id128_is_allf(SD_ID128_ALLF));
.fi
.if n \{\
.RE
.\}
.PP
\fBsd_id128_in_set_sentinel()\fR
takes a list of IDs and returns true if the first argument is equal to any of the subsequent arguments\&. The argument list is terminated by an
\fBSD_ID128_NULL\fR
sentinel, which must be present\&.
.PP
\fBsd_id128_in_set()\fR
is a convenience function that takes a list of IDs and returns true if the first argument is equal to any of the subsequent arguments:
.sp
.if n \{\
.RS 4
.\}
.nf
int main(int argc, char *argv[]) {
sd_id12_t a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
assert(sd_id128_in_set(a, a));
assert(sd_id128_in_set(a, a, a));
assert(!sd_id128_in_set(a));
assert(!sd_id128_in_set(a,
SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e)
SD_ID128_MAKE(2f,88,28,5f,9c,44,09,9d,d7,15,77,04,bc,85,7e,e3)
SD_ID128_ALLF));
return 0;
}
.fi
.if n \{\
.RE
.\}
.PP
\fBsd_id128_in_set()\fR
is defined as a macro over
\fBsd_id128_in_set_sentinel()\fR, adding the
\fBSD_ID128_NULL\fR
sentinel automatically\&. Since
\fBsd_id128_in_set_sentinel()\fR
uses
\fBSD_ID128_NULL\fR
as the sentinel,
\fBSD_ID128_NULL\fR
cannot be otherwise placed in the argument list\&.
.PP
\fBsd_id128_in_setv()\fR
is similar to
\fBsd_id128_in_set_sentinel()\fR, but takes a
struct varargs
argument\&.
.PP
New randomized IDs may be generated with
\fBsystemd-id128\fR(1)\*(Aqs
\fBnew\fR
command\&.
.PP
See
\fBsd_id128_to_string\fR(3),
\fBsd_id128_randomize\fR(3)
and
\fBsd_id128_get_machine\fR(3)
for information about other implemented functions\&.
.SH "NOTES"
.PP
Functions described here are available as a shared library, which can be compiled against and linked to with the
\fBlibsystemd\fR\ \&\fBpkg-config\fR(1)
file\&.
.PP
The code described here uses
\fBgetenv\fR(3), which is declared to be not multi\-thread\-safe\&. This means that the code calling the functions described here must not call
\fBsetenv\fR(3)
from a parallel thread\&. It is recommended to only do calls to
\fBsetenv()\fR
from an early phase of the program when no other threads have been started\&.
.SH "HISTORY"
.PP
\fBsd_id128_equal()\fR,
\fBsd_id128_string_equal()\fR,
\fBsd_id128_is_null()\fR,
\fBsd_id128_is_allf()\fR,
\fBsd_id128_in_setv()\fR,
\fBsd_id128_in_set_sentinel()\fR, and
\fBsd_id128_in_set()\fR
were added in version 252\&.
.SH "SEE ALSO"
.PP
\fBsystemd\fR(1), \fBsd_id128_to_string\fR(3), \fBsd_id128_randomize\fR(3), \fBsd_id128_get_machine\fR(3), \fBprintf\fR(3), \fBjournalctl\fR(1), \fBsd-journal\fR(7), \fBpkg-config\fR(1), \fBmachine-id\fR(5)
.SH "NOTES"
.IP " 1." 4
RFC 4122
.RS 4
\%https://tools.ietf.org/html/rfc4122
.RE
.IP " 2." 4
UUID canonical representation
.RS 4
\%https://en.wikipedia.org/wiki/Universally_unique_identifier#Format
.RE
|