xref: /dpdk/lib/eal/common/eal_common_uuid.c (revision 99a2dd955fba6e4cc23b77d590a033650ced9c45)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (C) 1996, 1997 Theodore Ts'o.
3  */
4 
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <ctype.h>
10 
11 #include <rte_uuid.h>
12 
13 /* UUID packed form */
14 struct uuid {
15 	uint32_t	time_low;
16 	uint16_t	time_mid;
17 	uint16_t	time_hi_and_version;
18 	uint16_t	clock_seq;
19 	uint8_t		node[6];
20 };
21 
uuid_pack(const struct uuid * uu,rte_uuid_t ptr)22 static void uuid_pack(const struct uuid *uu, rte_uuid_t ptr)
23 {
24 	uint32_t tmp;
25 	uint8_t	*out = ptr;
26 
27 	tmp = uu->time_low;
28 	out[3] = (uint8_t) tmp;
29 	tmp >>= 8;
30 	out[2] = (uint8_t) tmp;
31 	tmp >>= 8;
32 	out[1] = (uint8_t) tmp;
33 	tmp >>= 8;
34 	out[0] = (uint8_t) tmp;
35 
36 	tmp = uu->time_mid;
37 	out[5] = (uint8_t) tmp;
38 	tmp >>= 8;
39 	out[4] = (uint8_t) tmp;
40 
41 	tmp = uu->time_hi_and_version;
42 	out[7] = (uint8_t) tmp;
43 	tmp >>= 8;
44 	out[6] = (uint8_t) tmp;
45 
46 	tmp = uu->clock_seq;
47 	out[9] = (uint8_t) tmp;
48 	tmp >>= 8;
49 	out[8] = (uint8_t) tmp;
50 
51 	memcpy(out+10, uu->node, 6);
52 }
53 
uuid_unpack(const rte_uuid_t in,struct uuid * uu)54 static void uuid_unpack(const rte_uuid_t in, struct uuid *uu)
55 {
56 	const uint8_t *ptr = in;
57 	uint32_t tmp;
58 
59 	tmp = *ptr++;
60 	tmp = (tmp << 8) | *ptr++;
61 	tmp = (tmp << 8) | *ptr++;
62 	tmp = (tmp << 8) | *ptr++;
63 	uu->time_low = tmp;
64 
65 	tmp = *ptr++;
66 	tmp = (tmp << 8) | *ptr++;
67 	uu->time_mid = tmp;
68 
69 	tmp = *ptr++;
70 	tmp = (tmp << 8) | *ptr++;
71 	uu->time_hi_and_version = tmp;
72 
73 	tmp = *ptr++;
74 	tmp = (tmp << 8) | *ptr++;
75 	uu->clock_seq = tmp;
76 
77 	memcpy(uu->node, ptr, 6);
78 }
79 
rte_uuid_is_null(const rte_uuid_t uu)80 bool rte_uuid_is_null(const rte_uuid_t uu)
81 {
82 	const uint8_t *cp = uu;
83 	int i;
84 
85 	for (i = 0; i < 16; i++)
86 		if (*cp++)
87 			return false;
88 	return true;
89 }
90 
91 /*
92  * rte_uuid_compare() - compare two UUIDs.
93  */
rte_uuid_compare(const rte_uuid_t uu1,const rte_uuid_t uu2)94 int rte_uuid_compare(const rte_uuid_t uu1, const rte_uuid_t uu2)
95 {
96 	struct uuid	uuid1, uuid2;
97 
98 	uuid_unpack(uu1, &uuid1);
99 	uuid_unpack(uu2, &uuid2);
100 
101 #define UUCMP(u1, u2) \
102 	do { if (u1 != u2) return (u1 < u2) ? -1 : 1; } while (0)
103 
104 	UUCMP(uuid1.time_low, uuid2.time_low);
105 	UUCMP(uuid1.time_mid, uuid2.time_mid);
106 	UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
107 	UUCMP(uuid1.clock_seq, uuid2.clock_seq);
108 #undef UUCMP
109 
110 	return memcmp(uuid1.node, uuid2.node, 6);
111 }
112 
rte_uuid_parse(const char * in,rte_uuid_t uu)113 int rte_uuid_parse(const char *in, rte_uuid_t uu)
114 {
115 	struct uuid	uuid;
116 	int		i;
117 	const char	*cp;
118 	char		buf[3];
119 
120 	if (strlen(in) != 36)
121 		return -1;
122 
123 	for (i = 0, cp = in; i <= 36; i++, cp++) {
124 		if ((i == 8) || (i == 13) || (i == 18) ||
125 		    (i == 23)) {
126 			if (*cp == '-')
127 				continue;
128 			else
129 				return -1;
130 		}
131 		if (i == 36)
132 			if (*cp == 0)
133 				continue;
134 		if (!isxdigit(*cp))
135 			return -1;
136 	}
137 
138 	uuid.time_low = strtoul(in, NULL, 16);
139 	uuid.time_mid = strtoul(in+9, NULL, 16);
140 	uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
141 	uuid.clock_seq = strtoul(in+19, NULL, 16);
142 	cp = in+24;
143 	buf[2] = 0;
144 
145 	for (i = 0; i < 6; i++) {
146 		buf[0] = *cp++;
147 		buf[1] = *cp++;
148 		uuid.node[i] = strtoul(buf, NULL, 16);
149 	}
150 
151 	uuid_pack(&uuid, uu);
152 	return 0;
153 }
154 
rte_uuid_unparse(const rte_uuid_t uu,char * out,size_t len)155 void rte_uuid_unparse(const rte_uuid_t uu, char *out, size_t len)
156 {
157 	struct uuid uuid;
158 
159 	uuid_unpack(uu, &uuid);
160 
161 	snprintf(out, len,
162 		 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
163 		uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
164 		uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
165 		uuid.node[0], uuid.node[1], uuid.node[2],
166 		uuid.node[3], uuid.node[4], uuid.node[5]);
167 }
168