| @@ -1,325 +1,343 @@ | | | @@ -1,325 +1,343 @@ |
1 | /* $NetBSD: gpt_uuid.c,v 1.16 2018/11/06 04:04:33 mrg Exp $ */ | | 1 | /* $NetBSD: gpt_uuid.c,v 1.17 2018/12/20 14:58:10 martin Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | * POSSIBILITY OF SUCH DAMAGE. | | 26 | * POSSIBILITY OF SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | #if HAVE_NBTOOL_CONFIG_H | | 29 | #if HAVE_NBTOOL_CONFIG_H |
30 | #include "nbtool_config.h" | | 30 | #include "nbtool_config.h" |
31 | #endif | | 31 | #endif |
32 | | | 32 | |
33 | #include <sys/cdefs.h> | | 33 | #include <sys/cdefs.h> |
34 | #ifdef __RCSID | | 34 | #ifdef __RCSID |
35 | __RCSID("$NetBSD: gpt_uuid.c,v 1.16 2018/11/06 04:04:33 mrg Exp $"); | | 35 | __RCSID("$NetBSD: gpt_uuid.c,v 1.17 2018/12/20 14:58:10 martin Exp $"); |
36 | #endif | | 36 | #endif |
37 | | | 37 | |
38 | #include <err.h> | | 38 | #include <err.h> |
39 | #include <fcntl.h> | | 39 | #include <fcntl.h> |
40 | #include <stdio.h> | | 40 | #include <stdio.h> |
41 | #include <unistd.h> | | 41 | #include <unistd.h> |
42 | | | 42 | |
43 | #include "map.h" | | 43 | #include "map.h" |
44 | #include "gpt.h" | | 44 | #include "gpt.h" |
45 | #include "gpt_private.h" | | 45 | #include "gpt_private.h" |
46 | | | 46 | |
47 | #if defined(HAVE_SYS_ENDIAN_H) || ! defined(HAVE_NBTOOL_CONFIG_H) | | 47 | #if defined(HAVE_SYS_ENDIAN_H) || ! defined(HAVE_NBTOOL_CONFIG_H) |
48 | #include <sys/endian.h> | | 48 | #include <sys/endian.h> |
49 | #endif | | 49 | #endif |
50 | | | 50 | |
51 | | | 51 | |
52 | const gpt_uuid_t gpt_uuid_nil; | | 52 | const gpt_uuid_t gpt_uuid_nil; |
53 | | | 53 | |
54 | struct dce_uuid { | | 54 | struct dce_uuid { |
55 | uint32_t time_low; | | 55 | uint32_t time_low; |
56 | uint16_t time_mid; | | 56 | uint16_t time_mid; |
57 | uint16_t time_hi_and_version; | | 57 | uint16_t time_hi_and_version; |
58 | uint8_t clock_seq_hi_and_reserved; | | 58 | uint8_t clock_seq_hi_and_reserved; |
59 | uint8_t clock_seq_low; | | 59 | uint8_t clock_seq_low; |
60 | uint8_t node[6]; | | 60 | uint8_t node[6]; |
61 | }; | | 61 | }; |
62 | | | 62 | |
63 | static const struct { | | 63 | static const struct { |
64 | struct dce_uuid u; | | 64 | struct dce_uuid u; |
65 | const char *n; | | 65 | const char *n; |
66 | const char *d; | | 66 | const char *d; |
67 | } gpt_nv[] = { | | 67 | } gpt_nv[] = { |
68 | { GPT_ENT_TYPE_APPLE_HFS, "apple", "Apple HFS" }, | | 68 | { GPT_ENT_TYPE_APPLE_HFS, "apple", "Apple HFS" }, |
69 | { GPT_ENT_TYPE_APPLE_UFS, "apple-ufs", "Apple UFS" }, | | 69 | { GPT_ENT_TYPE_APPLE_UFS, "apple-ufs", "Apple UFS" }, |
70 | { GPT_ENT_TYPE_BIOS, "bios", "BIOS Boot" }, | | 70 | { GPT_ENT_TYPE_BIOS, "bios", "BIOS Boot" }, |
71 | { GPT_ENT_TYPE_EFI, "efi", "EFI System" }, | | 71 | { GPT_ENT_TYPE_EFI, "efi", "EFI System" }, |
72 | { GPT_ENT_TYPE_FREEBSD, "fbsd-legacy", "FreeBSD legacy" }, | | 72 | { GPT_ENT_TYPE_FREEBSD, "fbsd-legacy", "FreeBSD legacy" }, |
73 | { GPT_ENT_TYPE_FREEBSD_SWAP, "fbsd-swap", "FreeBSD swap" }, | | 73 | { GPT_ENT_TYPE_FREEBSD_SWAP, "fbsd-swap", "FreeBSD swap" }, |
74 | { GPT_ENT_TYPE_FREEBSD_UFS, "fbsd-ufs", "FreeBSD UFS/UFS2" }, | | 74 | { GPT_ENT_TYPE_FREEBSD_UFS, "fbsd-ufs", "FreeBSD UFS/UFS2" }, |
75 | { GPT_ENT_TYPE_FREEBSD_VINUM, "fbsd-vinum", "FreeBSD vinum" }, | | 75 | { GPT_ENT_TYPE_FREEBSD_VINUM, "fbsd-vinum", "FreeBSD vinum" }, |
76 | { GPT_ENT_TYPE_FREEBSD_ZFS, "fbsd-zfs", "FreeBSD ZFS" }, | | 76 | { GPT_ENT_TYPE_FREEBSD_ZFS, "fbsd-zfs", "FreeBSD ZFS" }, |
77 | { GPT_ENT_TYPE_LINUX_DATA, "linux-data", "Linux data" }, | | 77 | { GPT_ENT_TYPE_LINUX_DATA, "linux-data", "Linux data" }, |
78 | { GPT_ENT_TYPE_LINUX_RAID, "linux-raid", "Linux RAID" }, | | 78 | { GPT_ENT_TYPE_LINUX_RAID, "linux-raid", "Linux RAID" }, |
79 | { GPT_ENT_TYPE_LINUX_SWAP, "linux-swap", "Linux swap" }, | | 79 | { GPT_ENT_TYPE_LINUX_SWAP, "linux-swap", "Linux swap" }, |
80 | { GPT_ENT_TYPE_LINUX_LVM, "linux-lvm", "Linux LVM" }, | | 80 | { GPT_ENT_TYPE_LINUX_LVM, "linux-lvm", "Linux LVM" }, |
81 | { GPT_ENT_TYPE_MS_BASIC_DATA, "windows", "Windows basic data" }, | | 81 | { GPT_ENT_TYPE_MS_BASIC_DATA, "windows", "Windows basic data" }, |
82 | { GPT_ENT_TYPE_MS_RESERVED, "windows-reserved", "Windows reserved" }, | | 82 | { GPT_ENT_TYPE_MS_RESERVED, "windows-reserved", "Windows reserved" }, |
83 | { GPT_ENT_TYPE_NETBSD_CCD, "ccd", "NetBSD ccd component" }, | | 83 | { GPT_ENT_TYPE_NETBSD_CCD, "ccd", "NetBSD ccd component" }, |
84 | { GPT_ENT_TYPE_NETBSD_CGD, "cgd", "NetBSD Cryptographic Disk" }, | | 84 | { GPT_ENT_TYPE_NETBSD_CGD, "cgd", "NetBSD Cryptographic Disk" }, |
85 | { GPT_ENT_TYPE_NETBSD_FFS, "ffs", "NetBSD FFSv1/FFSv2" }, | | 85 | { GPT_ENT_TYPE_NETBSD_FFS, "ffs", "NetBSD FFSv1/FFSv2" }, |
86 | { GPT_ENT_TYPE_NETBSD_LFS, "lfs", "NetBSD LFS" }, | | 86 | { GPT_ENT_TYPE_NETBSD_LFS, "lfs", "NetBSD LFS" }, |
87 | { GPT_ENT_TYPE_NETBSD_RAIDFRAME, "raid", | | 87 | { GPT_ENT_TYPE_NETBSD_RAIDFRAME, "raid", |
88 | "NetBSD RAIDFrame component" }, | | 88 | "NetBSD RAIDFrame component" }, |
89 | { GPT_ENT_TYPE_NETBSD_SWAP, "swap", "NetBSD swap" }, | | 89 | { GPT_ENT_TYPE_NETBSD_SWAP, "swap", "NetBSD swap" }, |
90 | { GPT_ENT_TYPE_VMWARE_VMKCORE, "swap", "VMware VMkernel core dump" }, | | 90 | { GPT_ENT_TYPE_VMWARE_VMKCORE, "vmcore", "VMware VMkernel core dump" }, |
91 | { GPT_ENT_TYPE_VMWARE_VMFS, "swap", "VMware VMFS" }, | | 91 | { GPT_ENT_TYPE_VMWARE_VMFS, "vmfs", "VMware VMFS" }, |
92 | { GPT_ENT_TYPE_VMWARE_RESERVED, "swap", "VMware reserved" }, | | 92 | { GPT_ENT_TYPE_VMWARE_RESERVED, "vmresered", "VMware reserved" }, |
93 | }; | | 93 | }; |
94 | | | 94 | |
95 | static void | | 95 | static void |
96 | gpt_uuid_to_dce(const gpt_uuid_t buf, struct dce_uuid *uuid) | | 96 | gpt_uuid_to_dce(const gpt_uuid_t buf, struct dce_uuid *uuid) |
97 | { | | 97 | { |
98 | const uint8_t *p = buf; | | 98 | const uint8_t *p = buf; |
99 | size_t i; | | 99 | size_t i; |
100 | | | 100 | |
101 | uuid->time_low = le32dec(p); | | 101 | uuid->time_low = le32dec(p); |
102 | uuid->time_mid = le16dec(p + 4); | | 102 | uuid->time_mid = le16dec(p + 4); |
103 | uuid->time_hi_and_version = le16dec(p + 6); | | 103 | uuid->time_hi_and_version = le16dec(p + 6); |
104 | uuid->clock_seq_hi_and_reserved = p[8]; | | 104 | uuid->clock_seq_hi_and_reserved = p[8]; |
105 | uuid->clock_seq_low = p[9]; | | 105 | uuid->clock_seq_low = p[9]; |
106 | for (i = 0; i < sizeof(uuid->node); i++) | | 106 | for (i = 0; i < sizeof(uuid->node); i++) |
107 | uuid->node[i] = p[10 + i]; | | 107 | uuid->node[i] = p[10 + i]; |
108 | } | | 108 | } |
109 | | | 109 | |
110 | static void | | 110 | static void |
111 | gpt_dce_to_uuid(const struct dce_uuid *uuid, uint8_t *buf) | | 111 | gpt_dce_to_uuid(const struct dce_uuid *uuid, uint8_t *buf) |
112 | { | | 112 | { |
113 | uint8_t *p = buf; | | 113 | uint8_t *p = buf; |
114 | size_t i; | | 114 | size_t i; |
115 | | | 115 | |
116 | le32enc(p, uuid->time_low); | | 116 | le32enc(p, uuid->time_low); |
117 | le16enc(p + 4, uuid->time_mid); | | 117 | le16enc(p + 4, uuid->time_mid); |
118 | le16enc(p + 6, uuid->time_hi_and_version); | | 118 | le16enc(p + 6, uuid->time_hi_and_version); |
119 | p[8] = uuid->clock_seq_hi_and_reserved; | | 119 | p[8] = uuid->clock_seq_hi_and_reserved; |
120 | p[9] = uuid->clock_seq_low; | | 120 | p[9] = uuid->clock_seq_low; |
121 | for (i = 0; i < sizeof(uuid->node); i++) | | 121 | for (i = 0; i < sizeof(uuid->node); i++) |
122 | p[10 + i] = uuid->node[i]; | | 122 | p[10 + i] = uuid->node[i]; |
123 | } | | 123 | } |
124 | | | 124 | |
125 | static int | | 125 | static int |
126 | gpt_uuid_numeric(char *buf, size_t bufsiz, const struct dce_uuid *u) | | 126 | gpt_uuid_numeric(char *buf, size_t bufsiz, const struct dce_uuid *u) |
127 | { | | 127 | { |
128 | return snprintf(buf, bufsiz, | | 128 | return snprintf(buf, bufsiz, |
129 | "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", | | 129 | "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
130 | u->time_low, u->time_mid, u->time_hi_and_version, | | 130 | u->time_low, u->time_mid, u->time_hi_and_version, |
131 | u->clock_seq_hi_and_reserved, u->clock_seq_low, u->node[0], | | 131 | u->clock_seq_hi_and_reserved, u->clock_seq_low, u->node[0], |
132 | u->node[1], u->node[2], u->node[3], u->node[4], u->node[5]); | | 132 | u->node[1], u->node[2], u->node[3], u->node[4], u->node[5]); |
133 | } | | 133 | } |
134 | | | 134 | |
135 | | | 135 | |
136 | static int | | 136 | static int |
137 | gpt_uuid_symbolic(char *buf, size_t bufsiz, const struct dce_uuid *u) | | 137 | gpt_uuid_symbolic(char *buf, size_t bufsiz, const struct dce_uuid *u) |
138 | { | | 138 | { |
139 | size_t i; | | 139 | size_t i; |
140 | | | 140 | |
141 | for (i = 0; i < __arraycount(gpt_nv); i++) | | 141 | for (i = 0; i < __arraycount(gpt_nv); i++) |
142 | if (memcmp(&gpt_nv[i].u, u, sizeof(*u)) == 0) | | 142 | if (memcmp(&gpt_nv[i].u, u, sizeof(*u)) == 0) |
143 | return (int)strlcpy(buf, gpt_nv[i].n, bufsiz); | | 143 | return (int)strlcpy(buf, gpt_nv[i].n, bufsiz); |
144 | return -1; | | 144 | return -1; |
145 | } | | 145 | } |
146 | | | 146 | |
147 | static int | | 147 | static int |
148 | gpt_uuid_descriptive(char *buf, size_t bufsiz, const struct dce_uuid *u) | | 148 | gpt_uuid_descriptive(char *buf, size_t bufsiz, const struct dce_uuid *u) |
149 | { | | 149 | { |
150 | size_t i; | | 150 | size_t i; |
151 | | | 151 | |
152 | for (i = 0; i < __arraycount(gpt_nv); i++) | | 152 | for (i = 0; i < __arraycount(gpt_nv); i++) |
153 | if (memcmp(&gpt_nv[i].u, u, sizeof(*u)) == 0) | | 153 | if (memcmp(&gpt_nv[i].u, u, sizeof(*u)) == 0) |
154 | return (int)strlcpy(buf, gpt_nv[i].d, bufsiz); | | 154 | return (int)strlcpy(buf, gpt_nv[i].d, bufsiz); |
155 | return -1; | | 155 | return -1; |
156 | } | | 156 | } |
157 | | | 157 | |
158 | int | | 158 | int |
159 | gpt_uuid_snprintf(char *buf, size_t bufsiz, const char *fmt, | | 159 | gpt_uuid_snprintf(char *buf, size_t bufsiz, const char *fmt, |
160 | const gpt_uuid_t uu) | | 160 | const gpt_uuid_t uu) |
161 | { | | 161 | { |
162 | struct dce_uuid u; | | 162 | struct dce_uuid u; |
163 | gpt_uuid_to_dce(uu, &u); | | 163 | gpt_uuid_to_dce(uu, &u); |
164 | | | 164 | |
165 | if (fmt[1] == 's') { | | 165 | if (fmt[1] == 's') { |
166 | int r; | | 166 | int r; |
167 | if ((r = gpt_uuid_symbolic(buf, bufsiz, &u)) != -1) | | 167 | if ((r = gpt_uuid_symbolic(buf, bufsiz, &u)) != -1) |
168 | return r; | | 168 | return r; |
169 | } | | 169 | } |
170 | if (fmt[1] == 'l') { | | 170 | if (fmt[1] == 'l') { |
171 | int r; | | 171 | int r; |
172 | if ((r = gpt_uuid_descriptive(buf, bufsiz, &u)) != -1) | | 172 | if ((r = gpt_uuid_descriptive(buf, bufsiz, &u)) != -1) |
173 | return r; | | 173 | return r; |
174 | } | | 174 | } |
175 | return gpt_uuid_numeric(buf, bufsiz, &u); | | 175 | return gpt_uuid_numeric(buf, bufsiz, &u); |
176 | } | | 176 | } |
177 | | | 177 | |
178 | static int | | 178 | static int |
179 | gpt_uuid_parse_numeric(const char *s, struct dce_uuid *u) | | 179 | gpt_uuid_parse_numeric(const char *s, struct dce_uuid *u) |
180 | { | | 180 | { |
181 | int n; | | 181 | int n; |
182 | | | 182 | |
183 | if (s == NULL || *s == '\0') { | | 183 | if (s == NULL || *s == '\0') { |
184 | memset(u, 0, sizeof(*u)); | | 184 | memset(u, 0, sizeof(*u)); |
185 | return 0; | | 185 | return 0; |
186 | } | | 186 | } |
187 | | | 187 | |
188 | n = sscanf(s, | | 188 | n = sscanf(s, |
189 | "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", | | 189 | "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", |
190 | &u->time_low, &u->time_mid, &u->time_hi_and_version, | | 190 | &u->time_low, &u->time_mid, &u->time_hi_and_version, |
191 | &u->clock_seq_hi_and_reserved, &u->clock_seq_low, &u->node[0], | | 191 | &u->clock_seq_hi_and_reserved, &u->clock_seq_low, &u->node[0], |
192 | &u->node[1], &u->node[2], &u->node[3], &u->node[4], &u->node[5]); | | 192 | &u->node[1], &u->node[2], &u->node[3], &u->node[4], &u->node[5]); |
193 | | | 193 | |
194 | /* Make sure we have all conversions. */ | | 194 | /* Make sure we have all conversions. */ |
195 | if (n != 11) | | 195 | if (n != 11) |
196 | return -1; | | 196 | return -1; |
197 | | | 197 | |
198 | /* We have a successful scan. Check semantics... */ | | 198 | /* We have a successful scan. Check semantics... */ |
199 | n = u->clock_seq_hi_and_reserved; | | 199 | n = u->clock_seq_hi_and_reserved; |
200 | if ((n & 0x80) != 0x00 && /* variant 0? */ | | 200 | if ((n & 0x80) != 0x00 && /* variant 0? */ |
201 | (n & 0xc0) != 0x80 && /* variant 1? */ | | 201 | (n & 0xc0) != 0x80 && /* variant 1? */ |
202 | (n & 0xe0) != 0xc0) /* variant 2? */ | | 202 | (n & 0xe0) != 0xc0) /* variant 2? */ |
203 | return -1; | | 203 | return -1; |
204 | return 0; | | 204 | return 0; |
205 | } | | 205 | } |
206 | | | 206 | |
207 | static int | | 207 | static int |
208 | gpt_uuid_parse_symbolic(const char *s, struct dce_uuid *u) | | 208 | gpt_uuid_parse_symbolic(const char *s, struct dce_uuid *u) |
209 | { | | 209 | { |
210 | size_t i; | | 210 | size_t i; |
211 | | | 211 | |
212 | for (i = 0; i < __arraycount(gpt_nv); i++) | | 212 | for (i = 0; i < __arraycount(gpt_nv); i++) |
213 | if (strcmp(gpt_nv[i].n, s) == 0) { | | 213 | if (strcmp(gpt_nv[i].n, s) == 0) { |
214 | *u = gpt_nv[i].u; | | 214 | *u = gpt_nv[i].u; |
215 | return 0; | | 215 | return 0; |
216 | } | | 216 | } |
217 | return -1; | | 217 | return -1; |
218 | } | | 218 | } |
219 | | | 219 | |
220 | int | | 220 | int |
221 | gpt_uuid_parse(const char *s, gpt_uuid_t uuid) | | 221 | gpt_uuid_parse(const char *s, gpt_uuid_t uuid) |
222 | { | | 222 | { |
223 | struct dce_uuid u; | | 223 | struct dce_uuid u; |
224 | | | 224 | |
225 | if (gpt_uuid_parse_numeric(s, &u) != -1) { | | 225 | if (gpt_uuid_parse_numeric(s, &u) != -1) { |
226 | gpt_dce_to_uuid(&u, uuid); | | 226 | gpt_dce_to_uuid(&u, uuid); |
227 | return 0; | | 227 | return 0; |
228 | } | | 228 | } |
229 | | | 229 | |
230 | if (gpt_uuid_parse_symbolic(s, &u) == -1) | | 230 | if (gpt_uuid_parse_symbolic(s, &u) == -1) |
231 | return -1; | | 231 | return -1; |
232 | | | 232 | |
233 | gpt_dce_to_uuid(&u, uuid); | | 233 | gpt_dce_to_uuid(&u, uuid); |
234 | return 0; | | 234 | return 0; |
235 | } | | 235 | } |
236 | | | 236 | |
| | | 237 | size_t |
| | | 238 | gpt_uuid_query( |
| | | 239 | void (*func)(const char *uuid, const char *short_name, const char *desc)) |
| | | 240 | { |
| | | 241 | size_t i; |
| | | 242 | char buf[64]; |
| | | 243 | |
| | | 244 | if (func != NULL) { |
| | | 245 | for (i = 0; i < __arraycount(gpt_nv); i++) { |
| | | 246 | gpt_uuid_numeric(buf, sizeof(buf), &gpt_nv[i].u); |
| | | 247 | (*func)(buf, gpt_nv[i].n, gpt_nv[i].d); |
| | | 248 | } |
| | | 249 | } |
| | | 250 | return __arraycount(gpt_nv); |
| | | 251 | } |
| | | 252 | |
| | | 253 | #ifndef GPT_UUID_QUERY_ONLY |
237 | void | | 254 | void |
238 | gpt_uuid_help(const char *prefix) | | 255 | gpt_uuid_help(const char *prefix) |
239 | { | | 256 | { |
240 | size_t i; | | 257 | size_t i; |
241 | | | 258 | |
242 | for (i = 0; i < __arraycount(gpt_nv); i++) | | 259 | for (i = 0; i < __arraycount(gpt_nv); i++) |
243 | printf("%s%18.18s\t%s\n", prefix, gpt_nv[i].n, gpt_nv[i].d); | | 260 | printf("%s%18.18s\t%s\n", prefix, gpt_nv[i].n, gpt_nv[i].d); |
244 | } | | 261 | } |
245 | | | 262 | |
246 | void | | 263 | void |
247 | gpt_uuid_create(gpt_type_t t, gpt_uuid_t u, uint16_t *b, size_t s) | | 264 | gpt_uuid_create(gpt_type_t t, gpt_uuid_t u, uint16_t *b, size_t s) |
248 | { | | 265 | { |
249 | gpt_dce_to_uuid(&gpt_nv[t].u, u); | | 266 | gpt_dce_to_uuid(&gpt_nv[t].u, u); |
250 | if (b) | | 267 | if (b) |
251 | utf8_to_utf16((const uint8_t *)gpt_nv[t].d, b, s / sizeof(*b)); | | 268 | utf8_to_utf16((const uint8_t *)gpt_nv[t].d, b, s / sizeof(*b)); |
252 | } | | 269 | } |
253 | | | 270 | |
254 | static int | | 271 | static int |
255 | gpt_uuid_random(gpt_t gpt, void *v, size_t n) | | 272 | gpt_uuid_random(gpt_t gpt, void *v, size_t n) |
256 | { | | 273 | { |
257 | int fd; | | 274 | int fd; |
258 | uint8_t *p; | | 275 | uint8_t *p; |
259 | ssize_t nread; | | 276 | ssize_t nread; |
260 | | | 277 | |
261 | /* Randomly generate the content. */ | | 278 | /* Randomly generate the content. */ |
262 | fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); | | 279 | fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); |
263 | if (fd == -1) { | | 280 | if (fd == -1) { |
264 | gpt_warn(gpt, "Can't open `/dev/urandom'"); | | 281 | gpt_warn(gpt, "Can't open `/dev/urandom'"); |
265 | return -1; | | 282 | return -1; |
266 | } | | 283 | } |
267 | for (p = v; n > 0; p += nread, n -= (size_t)nread) { | | 284 | for (p = v; n > 0; p += nread, n -= (size_t)nread) { |
268 | nread = read(fd, p, n); | | 285 | nread = read(fd, p, n); |
269 | if (nread < 0) { | | 286 | if (nread < 0) { |
270 | gpt_warn(gpt, "Can't read `/dev/urandom'"); | | 287 | gpt_warn(gpt, "Can't read `/dev/urandom'"); |
271 | goto out; | | 288 | goto out; |
272 | } | | 289 | } |
273 | if (nread == 0) { | | 290 | if (nread == 0) { |
274 | gpt_warn(gpt, "EOF from /dev/urandom"); | | 291 | gpt_warn(gpt, "EOF from /dev/urandom"); |
275 | goto out; | | 292 | goto out; |
276 | } | | 293 | } |
277 | if ((size_t)nread > n) { | | 294 | if ((size_t)nread > n) { |
278 | gpt_warnx(gpt, "read too much: %zd > %zu", nread, n); | | 295 | gpt_warnx(gpt, "read too much: %zd > %zu", nread, n); |
279 | goto out; | | 296 | goto out; |
280 | } | | 297 | } |
281 | } | | 298 | } |
282 | (void)close(fd); | | 299 | (void)close(fd); |
283 | return 0; | | 300 | return 0; |
284 | out: | | 301 | out: |
285 | (void)close(fd); | | 302 | (void)close(fd); |
286 | return -1; | | 303 | return -1; |
287 | } | | 304 | } |
288 | | | 305 | |
289 | static int | | 306 | static int |
290 | gpt_uuid_tstamp(gpt_t gpt, void *v, size_t l) | | 307 | gpt_uuid_tstamp(gpt_t gpt, void *v, size_t l) |
291 | { | | 308 | { |
292 | uint8_t *p; | | 309 | uint8_t *p; |
293 | // Perhaps use SHA? | | 310 | // Perhaps use SHA? |
294 | uint32_t x = (uint32_t)gpt->timestamp; | | 311 | uint32_t x = (uint32_t)gpt->timestamp; |
295 | | | 312 | |
296 | for (p = v; l > 0; p += sizeof(x), l -= sizeof(x)) | | 313 | for (p = v; l > 0; p += sizeof(x), l -= sizeof(x)) |
297 | memcpy(p, &x, sizeof(x)); | | 314 | memcpy(p, &x, sizeof(x)); |
298 | | | 315 | |
299 | return 0; | | 316 | return 0; |
300 | } | | 317 | } |
301 | | | 318 | |
302 | int | | 319 | int |
303 | gpt_uuid_generate(gpt_t gpt, gpt_uuid_t t) | | 320 | gpt_uuid_generate(gpt_t gpt, gpt_uuid_t t) |
304 | { | | 321 | { |
305 | int rv; | | 322 | int rv; |
306 | struct dce_uuid u; | | 323 | struct dce_uuid u; |
307 | if (gpt->flags & GPT_TIMESTAMP) | | 324 | if (gpt->flags & GPT_TIMESTAMP) |
308 | rv = gpt_uuid_tstamp(gpt, &u, sizeof(u)); | | 325 | rv = gpt_uuid_tstamp(gpt, &u, sizeof(u)); |
309 | else | | 326 | else |
310 | rv = gpt_uuid_random(gpt, &u, sizeof(u)); | | 327 | rv = gpt_uuid_random(gpt, &u, sizeof(u)); |
311 | | | 328 | |
312 | if (rv == -1) | | 329 | if (rv == -1) |
313 | return -1; | | 330 | return -1; |
314 | | | 331 | |
315 | /* Set the version number to 4. */ | | 332 | /* Set the version number to 4. */ |
316 | u.time_hi_and_version &= (uint16_t)~0xf000; | | 333 | u.time_hi_and_version &= (uint16_t)~0xf000; |
317 | u.time_hi_and_version |= 0x4000; | | 334 | u.time_hi_and_version |= 0x4000; |
318 | | | 335 | |
319 | /* Fix the reserved bits. */ | | 336 | /* Fix the reserved bits. */ |
320 | u.clock_seq_hi_and_reserved &= (uint8_t)~0x40; | | 337 | u.clock_seq_hi_and_reserved &= (uint8_t)~0x40; |
321 | u.clock_seq_hi_and_reserved |= 0x80; | | 338 | u.clock_seq_hi_and_reserved |= 0x80; |
322 | | | 339 | |
323 | gpt_dce_to_uuid(&u, t); | | 340 | gpt_dce_to_uuid(&u, t); |
324 | return 0; | | 341 | return 0; |
325 | } | | 342 | } |
| | | 343 | #endif |