xref: /dragonfly/sbin/gpt/gpt.c (revision cbfa2b02)
1fb9cffefSMatthew Dillon /*-
2fb9cffefSMatthew Dillon  * Copyright (c) 2002 Marcel Moolenaar
3fb9cffefSMatthew Dillon  * All rights reserved.
4fb9cffefSMatthew Dillon  *
5fb9cffefSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
6fb9cffefSMatthew Dillon  * modification, are permitted provided that the following conditions
7fb9cffefSMatthew Dillon  * are met:
8fb9cffefSMatthew Dillon  *
9fb9cffefSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
10fb9cffefSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
11fb9cffefSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
12fb9cffefSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in the
13fb9cffefSMatthew Dillon  *    documentation and/or other materials provided with the distribution.
14fb9cffefSMatthew Dillon  *
15fb9cffefSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16fb9cffefSMatthew Dillon  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17fb9cffefSMatthew Dillon  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18fb9cffefSMatthew Dillon  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19fb9cffefSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20fb9cffefSMatthew Dillon  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21fb9cffefSMatthew Dillon  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22fb9cffefSMatthew Dillon  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23fb9cffefSMatthew Dillon  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24fb9cffefSMatthew Dillon  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25fb9cffefSMatthew Dillon  *
26fb9cffefSMatthew Dillon  * CRC32 code derived from work by Gary S. Brown.
27fb9cffefSMatthew Dillon  *
28fb9cffefSMatthew Dillon  * $FreeBSD: src/sbin/gpt/gpt.c,v 1.16 2006/07/07 02:44:23 marcel Exp $
29fb9cffefSMatthew Dillon  */
30fb9cffefSMatthew Dillon 
31fb9cffefSMatthew Dillon #include <sys/param.h>
32fb9cffefSMatthew Dillon #include <sys/types.h>
33fb9cffefSMatthew Dillon #include <sys/stat.h>
34fb9cffefSMatthew Dillon #include <sys/diskslice.h>
35fb9cffefSMatthew Dillon 
36fb9cffefSMatthew Dillon #include <err.h>
37fb9cffefSMatthew Dillon #include <errno.h>
38fb9cffefSMatthew Dillon #include <fcntl.h>
39fb9cffefSMatthew Dillon #include <paths.h>
40fb9cffefSMatthew Dillon #include <stddef.h>
41fb9cffefSMatthew Dillon #include <stdio.h>
42fb9cffefSMatthew Dillon #include <stdlib.h>
43fb9cffefSMatthew Dillon #include <string.h>
44fb9cffefSMatthew Dillon #include <unistd.h>
45fb9cffefSMatthew Dillon 
46fb9cffefSMatthew Dillon #include "map.h"
47fb9cffefSMatthew Dillon #include "gpt.h"
48fb9cffefSMatthew Dillon 
49fb9cffefSMatthew Dillon char	*device_name;
50fb9cffefSMatthew Dillon 
51fb9cffefSMatthew Dillon off_t	mediasz;
52fb9cffefSMatthew Dillon 
53fb9cffefSMatthew Dillon u_int	parts;
54fb9cffefSMatthew Dillon u_int	secsz;
55fb9cffefSMatthew Dillon 
56fb9cffefSMatthew Dillon int	readonly, verbose;
57fb9cffefSMatthew Dillon 
58fb9cffefSMatthew Dillon static uint32_t crc32_tab[] = {
59fb9cffefSMatthew Dillon 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
60fb9cffefSMatthew Dillon 	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
61fb9cffefSMatthew Dillon 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
62fb9cffefSMatthew Dillon 	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
63fb9cffefSMatthew Dillon 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,
64fb9cffefSMatthew Dillon 	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
65fb9cffefSMatthew Dillon 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,
66fb9cffefSMatthew Dillon 	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
67fb9cffefSMatthew Dillon 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
68fb9cffefSMatthew Dillon 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
69fb9cffefSMatthew Dillon 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,
70fb9cffefSMatthew Dillon 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
71fb9cffefSMatthew Dillon 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
72fb9cffefSMatthew Dillon 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
73fb9cffefSMatthew Dillon 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
74fb9cffefSMatthew Dillon 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
75fb9cffefSMatthew Dillon 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
76fb9cffefSMatthew Dillon 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
77fb9cffefSMatthew Dillon 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
78fb9cffefSMatthew Dillon 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
79fb9cffefSMatthew Dillon 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
80fb9cffefSMatthew Dillon 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
81fb9cffefSMatthew Dillon 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
82fb9cffefSMatthew Dillon 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
83fb9cffefSMatthew Dillon 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
84fb9cffefSMatthew Dillon 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
85fb9cffefSMatthew Dillon 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
86fb9cffefSMatthew Dillon 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
87fb9cffefSMatthew Dillon 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
88fb9cffefSMatthew Dillon 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
89fb9cffefSMatthew Dillon 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
90fb9cffefSMatthew Dillon 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
91fb9cffefSMatthew Dillon 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
92fb9cffefSMatthew Dillon 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
93fb9cffefSMatthew Dillon 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
94fb9cffefSMatthew Dillon 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
95fb9cffefSMatthew Dillon 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
96fb9cffefSMatthew Dillon 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
97fb9cffefSMatthew Dillon 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
98fb9cffefSMatthew Dillon 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
99fb9cffefSMatthew Dillon 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
100fb9cffefSMatthew Dillon 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
101fb9cffefSMatthew Dillon 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
102fb9cffefSMatthew Dillon };
103fb9cffefSMatthew Dillon 
104fb9cffefSMatthew Dillon uint32_t
crc32(const void * buf,size_t size)105fb9cffefSMatthew Dillon crc32(const void *buf, size_t size)
106fb9cffefSMatthew Dillon {
107fb9cffefSMatthew Dillon 	const uint8_t *p;
108fb9cffefSMatthew Dillon 	uint32_t crc;
109fb9cffefSMatthew Dillon 
110fb9cffefSMatthew Dillon 	p = buf;
111fb9cffefSMatthew Dillon 	crc = ~0U;
112fb9cffefSMatthew Dillon 
113fb9cffefSMatthew Dillon 	while (size--)
114fb9cffefSMatthew Dillon 		crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
115fb9cffefSMatthew Dillon 
116fb9cffefSMatthew Dillon 	return crc ^ ~0U;
117fb9cffefSMatthew Dillon }
118fb9cffefSMatthew Dillon 
119fb9cffefSMatthew Dillon uint8_t *
utf16_to_utf8(uint16_t * s16)120fb9cffefSMatthew Dillon utf16_to_utf8(uint16_t *s16)
121fb9cffefSMatthew Dillon {
122fb9cffefSMatthew Dillon 	static uint8_t *s8 = NULL;
123fb9cffefSMatthew Dillon 	static size_t s8len = 0;
124fb9cffefSMatthew Dillon 	size_t s8idx, s16idx, s16len;
125fb9cffefSMatthew Dillon 	uint32_t utfchar;
126fb9cffefSMatthew Dillon 	unsigned int c;
127fb9cffefSMatthew Dillon 
128fb9cffefSMatthew Dillon 	s16len = 0;
129fb9cffefSMatthew Dillon 	while (s16[s16len++] != 0)
130fb9cffefSMatthew Dillon 		;
131fb9cffefSMatthew Dillon 	if (s8len < s16len * 3) {
132fb9cffefSMatthew Dillon 		if (s8 != NULL)
133fb9cffefSMatthew Dillon 			free(s8);
134fb9cffefSMatthew Dillon 		s8len = s16len * 3;
135fb9cffefSMatthew Dillon 		s8 = calloc(s16len, 3);
136fb9cffefSMatthew Dillon 	}
137fb9cffefSMatthew Dillon 	s8idx = s16idx = 0;
138fb9cffefSMatthew Dillon 	while (s16idx < s16len) {
139fb9cffefSMatthew Dillon 		utfchar = le16toh(s16[s16idx++]);
140fb9cffefSMatthew Dillon 		if ((utfchar & 0xf800) == 0xd800) {
141fb9cffefSMatthew Dillon 			c = le16toh(s16[s16idx]);
142fb9cffefSMatthew Dillon 			if ((utfchar & 0x400) != 0 || (c & 0xfc00) != 0xdc00)
143fb9cffefSMatthew Dillon 				utfchar = 0xfffd;
144fb9cffefSMatthew Dillon 			else
145fb9cffefSMatthew Dillon 				s16idx++;
146fb9cffefSMatthew Dillon 		}
147fb9cffefSMatthew Dillon 		if (utfchar < 0x80) {
148fb9cffefSMatthew Dillon 			s8[s8idx++] = utfchar;
149fb9cffefSMatthew Dillon 		} else if (utfchar < 0x800) {
150fb9cffefSMatthew Dillon 			s8[s8idx++] = 0xc0 | (utfchar >> 6);
151fb9cffefSMatthew Dillon 			s8[s8idx++] = 0x80 | (utfchar & 0x3f);
152fb9cffefSMatthew Dillon 		} else if (utfchar < 0x10000) {
153fb9cffefSMatthew Dillon 			s8[s8idx++] = 0xe0 | (utfchar >> 12);
154fb9cffefSMatthew Dillon 			s8[s8idx++] = 0x80 | ((utfchar >> 6) & 0x3f);
155fb9cffefSMatthew Dillon 			s8[s8idx++] = 0x80 | (utfchar & 0x3f);
156fb9cffefSMatthew Dillon 		} else if (utfchar < 0x200000) {
157fb9cffefSMatthew Dillon 			s8[s8idx++] = 0xf0 | (utfchar >> 18);
158fb9cffefSMatthew Dillon 			s8[s8idx++] = 0x80 | ((utfchar >> 12) & 0x3f);
159fb9cffefSMatthew Dillon 			s8[s8idx++] = 0x80 | ((utfchar >> 6) & 0x3f);
160fb9cffefSMatthew Dillon 			s8[s8idx++] = 0x80 | (utfchar & 0x3f);
161fb9cffefSMatthew Dillon 		}
162fb9cffefSMatthew Dillon 	}
163fb9cffefSMatthew Dillon 	return (s8);
164fb9cffefSMatthew Dillon }
165fb9cffefSMatthew Dillon 
166fb9cffefSMatthew Dillon void
utf8_to_utf16(const uint8_t * s8,uint16_t * s16,size_t s16len)167fb9cffefSMatthew Dillon utf8_to_utf16(const uint8_t *s8, uint16_t *s16, size_t s16len)
168fb9cffefSMatthew Dillon {
169fb9cffefSMatthew Dillon 	size_t s16idx, s8idx, s8len;
170fb9cffefSMatthew Dillon 	uint32_t utfchar;
171fb9cffefSMatthew Dillon 	unsigned int c, utfbytes;
172fb9cffefSMatthew Dillon 
173fb9cffefSMatthew Dillon 	s8len = 0;
174fb9cffefSMatthew Dillon 	while (s8[s8len++] != 0)
175fb9cffefSMatthew Dillon 		;
176fb9cffefSMatthew Dillon 	s8idx = s16idx = 0;
177fb9cffefSMatthew Dillon 	utfbytes = 0;
178fb9cffefSMatthew Dillon 	do {
179fb9cffefSMatthew Dillon 		utfchar = 0;
180fb9cffefSMatthew Dillon 		c = s8[s8idx++];
181fb9cffefSMatthew Dillon 		if ((c & 0xc0) != 0x80) {
182fb9cffefSMatthew Dillon 			/* Initial characters. */
183fb9cffefSMatthew Dillon 			if (utfbytes != 0) {
184fb9cffefSMatthew Dillon 				/* Incomplete encoding. */
185fb9cffefSMatthew Dillon 				s16[s16idx++] = 0xfffd;
186fb9cffefSMatthew Dillon 				if (s16idx == s16len) {
187fb9cffefSMatthew Dillon 					s16[--s16idx] = 0;
188fb9cffefSMatthew Dillon 					return;
189fb9cffefSMatthew Dillon 				}
190fb9cffefSMatthew Dillon 			}
191fb9cffefSMatthew Dillon 			if ((c & 0xf8) == 0xf0) {
192fb9cffefSMatthew Dillon 				utfchar = c & 0x07;
193fb9cffefSMatthew Dillon 				utfbytes = 3;
194fb9cffefSMatthew Dillon 			} else if ((c & 0xf0) == 0xe0) {
195fb9cffefSMatthew Dillon 				utfchar = c & 0x0f;
196fb9cffefSMatthew Dillon 				utfbytes = 2;
197fb9cffefSMatthew Dillon 			} else if ((c & 0xe0) == 0xc0) {
198fb9cffefSMatthew Dillon 				utfchar = c & 0x1f;
199fb9cffefSMatthew Dillon 				utfbytes = 1;
200fb9cffefSMatthew Dillon 			} else {
201fb9cffefSMatthew Dillon 				utfchar = c & 0x7f;
202fb9cffefSMatthew Dillon 				utfbytes = 0;
203fb9cffefSMatthew Dillon 			}
204fb9cffefSMatthew Dillon 		} else {
205fb9cffefSMatthew Dillon 			/* Followup characters. */
206fb9cffefSMatthew Dillon 			if (utfbytes > 0) {
207fb9cffefSMatthew Dillon 				utfchar = (utfchar << 6) + (c & 0x3f);
208fb9cffefSMatthew Dillon 				utfbytes--;
209fb9cffefSMatthew Dillon 			} else if (utfbytes == 0)
210fb9cffefSMatthew Dillon 				utfbytes = -1;
211fb9cffefSMatthew Dillon 		}
212fb9cffefSMatthew Dillon 		if (utfbytes == 0) {
213fb9cffefSMatthew Dillon 			if (utfchar >= 0x10000 && s16idx + 2 >= s16len)
214fb9cffefSMatthew Dillon 				utfchar = 0xfffd;
215fb9cffefSMatthew Dillon 			if (utfchar >= 0x10000) {
216fb9cffefSMatthew Dillon 				s16[s16idx++] = 0xd800 | ((utfchar>>10)-0x40);
217fb9cffefSMatthew Dillon 				s16[s16idx++] = 0xdc00 | (utfchar & 0x3ff);
218fb9cffefSMatthew Dillon 			} else
219fb9cffefSMatthew Dillon 				s16[s16idx++] = utfchar;
220fb9cffefSMatthew Dillon 			if (s16idx == s16len) {
221fb9cffefSMatthew Dillon 				s16[--s16idx] = 0;
222fb9cffefSMatthew Dillon 				return;
223fb9cffefSMatthew Dillon 			}
224fb9cffefSMatthew Dillon 		}
225fb9cffefSMatthew Dillon 	} while (c != 0);
226fb9cffefSMatthew Dillon }
227fb9cffefSMatthew Dillon 
228fb9cffefSMatthew Dillon void
le_uuid_dec(void const * buf,uuid_t * uuid)229fb9cffefSMatthew Dillon le_uuid_dec(void const *buf, uuid_t *uuid)
230fb9cffefSMatthew Dillon {
231fb9cffefSMatthew Dillon 	u_char const *p;
232fb9cffefSMatthew Dillon 	int i;
233fb9cffefSMatthew Dillon 
234fb9cffefSMatthew Dillon 	p = buf;
235fb9cffefSMatthew Dillon 	uuid->time_low = le32dec(p);
236fb9cffefSMatthew Dillon 	uuid->time_mid = le16dec(p + 4);
237fb9cffefSMatthew Dillon 	uuid->time_hi_and_version = le16dec(p + 6);
238fb9cffefSMatthew Dillon 	uuid->clock_seq_hi_and_reserved = p[8];
239fb9cffefSMatthew Dillon 	uuid->clock_seq_low = p[9];
240fb9cffefSMatthew Dillon 	for (i = 0; i < _UUID_NODE_LEN; i++)
241fb9cffefSMatthew Dillon 		uuid->node[i] = p[10 + i];
242fb9cffefSMatthew Dillon }
243fb9cffefSMatthew Dillon 
244fb9cffefSMatthew Dillon void
le_uuid_enc(void * buf,uuid_t const * uuid)245fb9cffefSMatthew Dillon le_uuid_enc(void *buf, uuid_t const *uuid)
246fb9cffefSMatthew Dillon {
247fb9cffefSMatthew Dillon 	u_char *p;
248fb9cffefSMatthew Dillon 	int i;
249fb9cffefSMatthew Dillon 
250fb9cffefSMatthew Dillon 	p = buf;
251fb9cffefSMatthew Dillon 	le32enc(p, uuid->time_low);
252fb9cffefSMatthew Dillon 	le16enc(p + 4, uuid->time_mid);
253fb9cffefSMatthew Dillon 	le16enc(p + 6, uuid->time_hi_and_version);
254fb9cffefSMatthew Dillon 	p[8] = uuid->clock_seq_hi_and_reserved;
255fb9cffefSMatthew Dillon 	p[9] = uuid->clock_seq_low;
256fb9cffefSMatthew Dillon 	for (i = 0; i < _UUID_NODE_LEN; i++)
257fb9cffefSMatthew Dillon 		p[10 + i] = uuid->node[i];
258fb9cffefSMatthew Dillon }
259fb9cffefSMatthew Dillon 
260fb9cffefSMatthew Dillon int
parse_uuid(const char * s,uuid_t * uuid)261fb9cffefSMatthew Dillon parse_uuid(const char *s, uuid_t *uuid)
262fb9cffefSMatthew Dillon {
263fb9cffefSMatthew Dillon 	uint32_t status;
26450d00bbdSMatthew Dillon 	uuid_t tmp;
265fb9cffefSMatthew Dillon 
266fb9cffefSMatthew Dillon 	uuid_from_string(s, uuid, &status);
267fb9cffefSMatthew Dillon 	if (status == uuid_s_ok)
268fb9cffefSMatthew Dillon 		return (0);
269fb9cffefSMatthew Dillon 
270fb9cffefSMatthew Dillon 	switch (*s) {
27150d00bbdSMatthew Dillon 	case 'd':
27250d00bbdSMatthew Dillon 		if (strcmp(s, "dfly") == 0 || strcmp(s, "dragonfly") == 0) {
273ba0cc1abSMatthew Dillon 			s = "DragonFly Label64";
27450d00bbdSMatthew Dillon 			/* fall through to lookup at end */
27550d00bbdSMatthew Dillon 		}
27650d00bbdSMatthew Dillon 		break;
277fb9cffefSMatthew Dillon 	case 'e':
278fb9cffefSMatthew Dillon 		if (strcmp(s, "efi") == 0) {
279fb9cffefSMatthew Dillon 			uuid_t efi = GPT_ENT_TYPE_EFI;
280fb9cffefSMatthew Dillon 			*uuid = efi;
281fb9cffefSMatthew Dillon 			return (0);
282fb9cffefSMatthew Dillon 		}
283fb9cffefSMatthew Dillon 		break;
284fb9cffefSMatthew Dillon 	case 'h':
28541d6e048SFrançois Tigeot 		if (strcmp(s, "hammer2") == 0) {
28641d6e048SFrançois Tigeot 			uuid_t hammer2 = GPT_ENT_TYPE_DRAGONFLY_HAMMER2;
28741d6e048SFrançois Tigeot 			*uuid = hammer2;
28841d6e048SFrançois Tigeot 			return (0);
28941d6e048SFrançois Tigeot 		}
29041d6e048SFrançois Tigeot 		if (strcmp(s, "hammer") == 0) {
29141d6e048SFrançois Tigeot 			uuid_t hammer = GPT_ENT_TYPE_DRAGONFLY_HAMMER;
29241d6e048SFrançois Tigeot 			*uuid = hammer;
29341d6e048SFrançois Tigeot 			return (0);
29441d6e048SFrançois Tigeot 		}
295fb9cffefSMatthew Dillon 		if (strcmp(s, "hfs") == 0) {
296fb9cffefSMatthew Dillon 			uuid_t hfs = GPT_ENT_TYPE_APPLE_HFS;
297fb9cffefSMatthew Dillon 			*uuid = hfs;
298fb9cffefSMatthew Dillon 			return (0);
299fb9cffefSMatthew Dillon 		}
300fb9cffefSMatthew Dillon 		break;
301fb9cffefSMatthew Dillon 	case 'l':
302fb9cffefSMatthew Dillon 		if (strcmp(s, "linux") == 0) {
303fb9cffefSMatthew Dillon 			uuid_t lnx = GPT_ENT_TYPE_MS_BASIC_DATA;
304fb9cffefSMatthew Dillon 			*uuid = lnx;
305fb9cffefSMatthew Dillon 			return (0);
306fb9cffefSMatthew Dillon 		}
307fb9cffefSMatthew Dillon 		break;
308fb9cffefSMatthew Dillon 	case 's':
309fb9cffefSMatthew Dillon 		if (strcmp(s, "swap") == 0) {
310fb9cffefSMatthew Dillon 			uuid_t sw = GPT_ENT_TYPE_FREEBSD_SWAP;
311fb9cffefSMatthew Dillon 			*uuid = sw;
312fb9cffefSMatthew Dillon 			return (0);
313fb9cffefSMatthew Dillon 		}
314fb9cffefSMatthew Dillon 		break;
315fb9cffefSMatthew Dillon 	case 'u':
316fb9cffefSMatthew Dillon 		if (strcmp(s, "ufs") == 0) {
317fb9cffefSMatthew Dillon 			uuid_t ufs = GPT_ENT_TYPE_FREEBSD_UFS;
318fb9cffefSMatthew Dillon 			*uuid = ufs;
319fb9cffefSMatthew Dillon 			return (0);
320fb9cffefSMatthew Dillon 		}
321fb9cffefSMatthew Dillon 		break;
322fb9cffefSMatthew Dillon 	case 'w':
323fb9cffefSMatthew Dillon 		if (strcmp(s, "windows") == 0) {
324fb9cffefSMatthew Dillon 			uuid_t win = GPT_ENT_TYPE_MS_BASIC_DATA;
325fb9cffefSMatthew Dillon 			*uuid = win;
326fb9cffefSMatthew Dillon 			return (0);
327fb9cffefSMatthew Dillon 		}
328fb9cffefSMatthew Dillon 		break;
329fb9cffefSMatthew Dillon 	}
33050d00bbdSMatthew Dillon 
33150d00bbdSMatthew Dillon 	uuid_name_lookup(&tmp, s, &status);
33250d00bbdSMatthew Dillon 	if (status == uuid_s_ok) {
33350d00bbdSMatthew Dillon 		*uuid = tmp;
33450d00bbdSMatthew Dillon 		return(0);
33550d00bbdSMatthew Dillon 	}
33650d00bbdSMatthew Dillon 
337fb9cffefSMatthew Dillon 	return (EINVAL);
338fb9cffefSMatthew Dillon }
339fb9cffefSMatthew Dillon 
340fb9cffefSMatthew Dillon void*
gpt_read(int fd,off_t lba,size_t count)341fb9cffefSMatthew Dillon gpt_read(int fd, off_t lba, size_t count)
342fb9cffefSMatthew Dillon {
343fb9cffefSMatthew Dillon 	off_t ofs;
344fb9cffefSMatthew Dillon 	void *buf;
345fb9cffefSMatthew Dillon 
346fb9cffefSMatthew Dillon 	count *= secsz;
347fb9cffefSMatthew Dillon 	buf = malloc(count);
348fb9cffefSMatthew Dillon 	if (buf == NULL)
349fb9cffefSMatthew Dillon 		return (NULL);
350fb9cffefSMatthew Dillon 
351fb9cffefSMatthew Dillon 	ofs = lba * secsz;
352fb9cffefSMatthew Dillon 	if (lseek(fd, ofs, SEEK_SET) == ofs &&
353fb9cffefSMatthew Dillon 	    read(fd, buf, count) == (ssize_t)count)
354fb9cffefSMatthew Dillon 		return (buf);
355fb9cffefSMatthew Dillon 
356fb9cffefSMatthew Dillon 	free(buf);
357fb9cffefSMatthew Dillon 	return (NULL);
358fb9cffefSMatthew Dillon }
359fb9cffefSMatthew Dillon 
360fb9cffefSMatthew Dillon int
gpt_write(int fd,map_t * map)361fb9cffefSMatthew Dillon gpt_write(int fd, map_t *map)
362fb9cffefSMatthew Dillon {
363fb9cffefSMatthew Dillon 	off_t ofs;
364fb9cffefSMatthew Dillon 	size_t count;
365fb9cffefSMatthew Dillon 
366fb9cffefSMatthew Dillon 	count = map->map_size * secsz;
367fb9cffefSMatthew Dillon 	ofs = map->map_start * secsz;
368fb9cffefSMatthew Dillon 	if (lseek(fd, ofs, SEEK_SET) == ofs &&
369fb9cffefSMatthew Dillon 	    write(fd, map->map_data, count) == (ssize_t)count)
370fb9cffefSMatthew Dillon 		return (0);
371fb9cffefSMatthew Dillon 	return (-1);
372fb9cffefSMatthew Dillon }
373fb9cffefSMatthew Dillon 
374fb9cffefSMatthew Dillon static int
gpt_mbr(int fd,off_t lba)375fb9cffefSMatthew Dillon gpt_mbr(int fd, off_t lba)
376fb9cffefSMatthew Dillon {
377fb9cffefSMatthew Dillon 	struct mbr *mbr;
378fb9cffefSMatthew Dillon 	map_t *m, *p;
379fb9cffefSMatthew Dillon 	off_t size, start;
380fb9cffefSMatthew Dillon 	unsigned int i, pmbr;
381fb9cffefSMatthew Dillon 
382fb9cffefSMatthew Dillon 	mbr = gpt_read(fd, lba, 1);
383fb9cffefSMatthew Dillon 	if (mbr == NULL)
384fb9cffefSMatthew Dillon 		return (-1);
385fb9cffefSMatthew Dillon 
386fb9cffefSMatthew Dillon 	if (mbr->mbr_sig != htole16(MBR_SIG)) {
387fb9cffefSMatthew Dillon 		if (verbose)
388fb9cffefSMatthew Dillon 			warnx("%s: MBR not found at sector %llu", device_name,
389fb9cffefSMatthew Dillon 			    (long long)lba);
390fb9cffefSMatthew Dillon 		free(mbr);
391fb9cffefSMatthew Dillon 		return (0);
392fb9cffefSMatthew Dillon 	}
393fb9cffefSMatthew Dillon 
394fb9cffefSMatthew Dillon 	/*
395fb9cffefSMatthew Dillon 	 * Differentiate between a regular MBR and a PMBR. This is more
396fb9cffefSMatthew Dillon 	 * convenient in general. A PMBR is one with a single partition
397fb9cffefSMatthew Dillon 	 * of type 0xee.
398fb9cffefSMatthew Dillon 	 */
399fb9cffefSMatthew Dillon 	pmbr = 0;
400fb9cffefSMatthew Dillon 	for (i = 0; i < 4; i++) {
401fb9cffefSMatthew Dillon 		if (mbr->mbr_part[i].part_typ == 0)
402fb9cffefSMatthew Dillon 			continue;
403fb9cffefSMatthew Dillon 		if (mbr->mbr_part[i].part_typ == 0xee)
404fb9cffefSMatthew Dillon 			pmbr++;
405fb9cffefSMatthew Dillon 		else
406fb9cffefSMatthew Dillon 			break;
407fb9cffefSMatthew Dillon 	}
408210143e4SMatthew Dillon 	if (pmbr && (i == 1 || i == 4) && lba == 0) {
409fb9cffefSMatthew Dillon 		if (pmbr != 1)
410fb9cffefSMatthew Dillon 			warnx("%s: Suspicious PMBR at sector %llu",
411fb9cffefSMatthew Dillon 			    device_name, (long long)lba);
412fb9cffefSMatthew Dillon 		else if (verbose > 1)
413fb9cffefSMatthew Dillon 			warnx("%s: PMBR at sector %llu", device_name,
414fb9cffefSMatthew Dillon 			    (long long)lba);
415fb9cffefSMatthew Dillon 		p = map_add(lba, 1LL, MAP_TYPE_PMBR, mbr);
416fb9cffefSMatthew Dillon 		return ((p == NULL) ? -1 : 0);
417fb9cffefSMatthew Dillon 	}
418fb9cffefSMatthew Dillon 	if (pmbr)
419fb9cffefSMatthew Dillon 		warnx("%s: Suspicious MBR at sector %llu", device_name,
420fb9cffefSMatthew Dillon 		    (long long)lba);
421fb9cffefSMatthew Dillon 	else if (verbose > 1)
422fb9cffefSMatthew Dillon 		warnx("%s: MBR at sector %llu", device_name, (long long)lba);
423fb9cffefSMatthew Dillon 
424fb9cffefSMatthew Dillon 	p = map_add(lba, 1LL, MAP_TYPE_MBR, mbr);
425fb9cffefSMatthew Dillon 	if (p == NULL)
426fb9cffefSMatthew Dillon 		return (-1);
427fb9cffefSMatthew Dillon 	for (i = 0; i < 4; i++) {
428fb9cffefSMatthew Dillon 		if (mbr->mbr_part[i].part_typ == 0 ||
429fb9cffefSMatthew Dillon 		    mbr->mbr_part[i].part_typ == 0xee)
430fb9cffefSMatthew Dillon 			continue;
431fb9cffefSMatthew Dillon 		start = le16toh(mbr->mbr_part[i].part_start_hi);
432fb9cffefSMatthew Dillon 		start = (start << 16) + le16toh(mbr->mbr_part[i].part_start_lo);
433fb9cffefSMatthew Dillon 		size = le16toh(mbr->mbr_part[i].part_size_hi);
434fb9cffefSMatthew Dillon 		size = (size << 16) + le16toh(mbr->mbr_part[i].part_size_lo);
435fb9cffefSMatthew Dillon 		if (start == 0 && size == 0) {
436fb9cffefSMatthew Dillon 			warnx("%s: Malformed MBR at sector %llu", device_name,
437fb9cffefSMatthew Dillon 			    (long long)lba);
438fb9cffefSMatthew Dillon 			continue;
439fb9cffefSMatthew Dillon 		}
440fb9cffefSMatthew Dillon 		/* start is relative to the offset of the MBR itself. */
441fb9cffefSMatthew Dillon 		start += lba;
442fb9cffefSMatthew Dillon 		if (verbose > 2)
443fb9cffefSMatthew Dillon 			warnx("%s: MBR part: type=%d, start=%llu, size=%llu",
444fb9cffefSMatthew Dillon 			    device_name, mbr->mbr_part[i].part_typ,
445fb9cffefSMatthew Dillon 			    (long long)start, (long long)size);
446fb9cffefSMatthew Dillon 		if (mbr->mbr_part[i].part_typ != 15) {
447fb9cffefSMatthew Dillon 			m = map_add(start, size, MAP_TYPE_MBR_PART, p);
448fb9cffefSMatthew Dillon 			if (m == NULL)
449fb9cffefSMatthew Dillon 				return (-1);
45071cfd094SMatthew Dillon 			m->map_index = i;
451fb9cffefSMatthew Dillon 		} else {
452fb9cffefSMatthew Dillon 			if (gpt_mbr(fd, start) == -1)
453fb9cffefSMatthew Dillon 				return (-1);
454fb9cffefSMatthew Dillon 		}
455fb9cffefSMatthew Dillon 	}
456fb9cffefSMatthew Dillon 	return (0);
457fb9cffefSMatthew Dillon }
458fb9cffefSMatthew Dillon 
459fb9cffefSMatthew Dillon static int
gpt_gpt(int fd,off_t lba)460fb9cffefSMatthew Dillon gpt_gpt(int fd, off_t lba)
461fb9cffefSMatthew Dillon {
462fb9cffefSMatthew Dillon 	uuid_t type;
463fb9cffefSMatthew Dillon 	off_t size;
464fb9cffefSMatthew Dillon 	struct gpt_ent *ent;
465fb9cffefSMatthew Dillon 	struct gpt_hdr *hdr;
466fb9cffefSMatthew Dillon 	char *p, *s;
467fb9cffefSMatthew Dillon 	map_t *m;
468fb9cffefSMatthew Dillon 	size_t blocks, tblsz;
469fb9cffefSMatthew Dillon 	unsigned int i;
470fb9cffefSMatthew Dillon 	uint32_t crc;
471fb9cffefSMatthew Dillon 
472fb9cffefSMatthew Dillon 	hdr = gpt_read(fd, lba, 1);
473fb9cffefSMatthew Dillon 	if (hdr == NULL)
474fb9cffefSMatthew Dillon 		return (-1);
475fb9cffefSMatthew Dillon 
476fb9cffefSMatthew Dillon 	if (memcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)))
477fb9cffefSMatthew Dillon 		goto fail_hdr;
478fb9cffefSMatthew Dillon 
479fb9cffefSMatthew Dillon 	crc = le32toh(hdr->hdr_crc_self);
480fb9cffefSMatthew Dillon 	hdr->hdr_crc_self = 0;
481fb9cffefSMatthew Dillon 	if (crc32(hdr, le32toh(hdr->hdr_size)) != crc) {
482fb9cffefSMatthew Dillon 		if (verbose)
483fb9cffefSMatthew Dillon 			warnx("%s: Bad CRC in GPT header at sector %llu",
484fb9cffefSMatthew Dillon 			    device_name, (long long)lba);
485fb9cffefSMatthew Dillon 		goto fail_hdr;
486fb9cffefSMatthew Dillon 	}
487fb9cffefSMatthew Dillon 
488fb9cffefSMatthew Dillon 	tblsz = le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz);
489fb9cffefSMatthew Dillon 	blocks = tblsz / secsz + ((tblsz % secsz) ? 1 : 0);
490fb9cffefSMatthew Dillon 
491fb9cffefSMatthew Dillon 	/* Use generic pointer to deal with hdr->hdr_entsz != sizeof(*ent). */
492fb9cffefSMatthew Dillon 	p = gpt_read(fd, le64toh(hdr->hdr_lba_table), blocks);
493fb9cffefSMatthew Dillon 	if (p == NULL)
494fb9cffefSMatthew Dillon 		return (-1);
495fb9cffefSMatthew Dillon 
496fb9cffefSMatthew Dillon 	if (crc32(p, tblsz) != le32toh(hdr->hdr_crc_table)) {
497fb9cffefSMatthew Dillon 		if (verbose)
498fb9cffefSMatthew Dillon 			warnx("%s: Bad CRC in GPT table at sector %llu",
499fb9cffefSMatthew Dillon 			    device_name,
500fb9cffefSMatthew Dillon 			    (long long)le64toh(hdr->hdr_lba_table));
501fb9cffefSMatthew Dillon 		goto fail_ent;
502fb9cffefSMatthew Dillon 	}
503fb9cffefSMatthew Dillon 
504fb9cffefSMatthew Dillon 	if (verbose > 1)
505fb9cffefSMatthew Dillon 		warnx("%s: %s GPT at sector %llu", device_name,
506fb9cffefSMatthew Dillon 		    (lba == 1) ? "Pri" : "Sec", (long long)lba);
507fb9cffefSMatthew Dillon 
508fb9cffefSMatthew Dillon 	m = map_add(lba, 1, (lba == 1)
509fb9cffefSMatthew Dillon 	    ? MAP_TYPE_PRI_GPT_HDR : MAP_TYPE_SEC_GPT_HDR, hdr);
510fb9cffefSMatthew Dillon 	if (m == NULL)
511fb9cffefSMatthew Dillon 		return (-1);
512fb9cffefSMatthew Dillon 
513fb9cffefSMatthew Dillon 	m = map_add(le64toh(hdr->hdr_lba_table), blocks, (lba == 1)
514fb9cffefSMatthew Dillon 	    ? MAP_TYPE_PRI_GPT_TBL : MAP_TYPE_SEC_GPT_TBL, p);
515fb9cffefSMatthew Dillon 	if (m == NULL)
516fb9cffefSMatthew Dillon 		return (-1);
517fb9cffefSMatthew Dillon 
518fb9cffefSMatthew Dillon 	if (lba != 1)
519fb9cffefSMatthew Dillon 		return (0);
520fb9cffefSMatthew Dillon 
521fb9cffefSMatthew Dillon 	for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
522fb9cffefSMatthew Dillon 		ent = (void*)(p + i * le32toh(hdr->hdr_entsz));
523fb9cffefSMatthew Dillon 		if (uuid_is_nil(&ent->ent_type, NULL))
524fb9cffefSMatthew Dillon 			continue;
525fb9cffefSMatthew Dillon 
526fb9cffefSMatthew Dillon 		size = le64toh(ent->ent_lba_end) - le64toh(ent->ent_lba_start) +
527fb9cffefSMatthew Dillon 		    1LL;
528fb9cffefSMatthew Dillon 		if (verbose > 2) {
529fb9cffefSMatthew Dillon 			le_uuid_dec(&ent->ent_type, &type);
530fb9cffefSMatthew Dillon 			uuid_to_string(&type, &s, NULL);
531fb9cffefSMatthew Dillon 			warnx(
532fb9cffefSMatthew Dillon 	"%s: GPT partition: type=%s, start=%llu, size=%llu", device_name, s,
533fb9cffefSMatthew Dillon 			    (long long)le64toh(ent->ent_lba_start),
534fb9cffefSMatthew Dillon 			    (long long)size);
535fb9cffefSMatthew Dillon 			free(s);
536fb9cffefSMatthew Dillon 		}
537fb9cffefSMatthew Dillon 		m = map_add(le64toh(ent->ent_lba_start), size,
538fb9cffefSMatthew Dillon 		    MAP_TYPE_GPT_PART, ent);
539fb9cffefSMatthew Dillon 		if (m == NULL)
540fb9cffefSMatthew Dillon 			return (-1);
54171cfd094SMatthew Dillon 		m->map_index = i;
542fb9cffefSMatthew Dillon 	}
543fb9cffefSMatthew Dillon 	return (0);
544fb9cffefSMatthew Dillon 
545fb9cffefSMatthew Dillon  fail_ent:
546fb9cffefSMatthew Dillon 	free(p);
547fb9cffefSMatthew Dillon 
548fb9cffefSMatthew Dillon  fail_hdr:
549fb9cffefSMatthew Dillon 	free(hdr);
550fb9cffefSMatthew Dillon 	return (0);
551fb9cffefSMatthew Dillon }
552fb9cffefSMatthew Dillon 
553fb9cffefSMatthew Dillon int
gpt_open(const char * dev)554fb9cffefSMatthew Dillon gpt_open(const char *dev)
555fb9cffefSMatthew Dillon {
556fb9cffefSMatthew Dillon 	struct stat sb;
557*cbfa2b02SMatthew Dillon 	static char device_path[MAXPATHLEN];
558fb9cffefSMatthew Dillon 	int fd, mode;
559fb9cffefSMatthew Dillon 
560fb9cffefSMatthew Dillon 	mode = readonly ? O_RDONLY : O_RDWR|O_EXCL;
561fb9cffefSMatthew Dillon 
562fb9cffefSMatthew Dillon 	strlcpy(device_path, dev, sizeof(device_path));
563fb9cffefSMatthew Dillon 	device_name = device_path;
564fb9cffefSMatthew Dillon 
565fb9cffefSMatthew Dillon 	if ((fd = open(device_path, mode)) != -1)
566fb9cffefSMatthew Dillon 		goto found;
567fb9cffefSMatthew Dillon 
568fb9cffefSMatthew Dillon 	snprintf(device_path, sizeof(device_path), "%s%s", _PATH_DEV, dev);
569fb9cffefSMatthew Dillon 	device_name = device_path + strlen(_PATH_DEV);
570fb9cffefSMatthew Dillon 	if ((fd = open(device_path, mode)) != -1)
571fb9cffefSMatthew Dillon 		goto found;
572fb9cffefSMatthew Dillon 
573fb9cffefSMatthew Dillon 	return (-1);
574fb9cffefSMatthew Dillon 
575fb9cffefSMatthew Dillon  found:
576fb9cffefSMatthew Dillon 	if (fstat(fd, &sb) == -1)
577fb9cffefSMatthew Dillon 		goto close;
578fb9cffefSMatthew Dillon 
579fb9cffefSMatthew Dillon 	if ((sb.st_mode & S_IFMT) != S_IFREG) {
580fb9cffefSMatthew Dillon 		struct partinfo partinfo;
581fb9cffefSMatthew Dillon 
582fb9cffefSMatthew Dillon 		if (ioctl(fd, DIOCGPART, &partinfo) < 0)
583fb9cffefSMatthew Dillon 			goto close;
584fb9cffefSMatthew Dillon 		secsz = partinfo.media_blksize;
585fb9cffefSMatthew Dillon 		mediasz = partinfo.media_size;
586fb9cffefSMatthew Dillon 	} else {
587fb9cffefSMatthew Dillon 		secsz = 512;	/* Fixed size for files. */
588fb9cffefSMatthew Dillon 		if (sb.st_size % secsz) {
589fb9cffefSMatthew Dillon 			errno = EINVAL;
590fb9cffefSMatthew Dillon 			goto close;
591fb9cffefSMatthew Dillon 		}
592fb9cffefSMatthew Dillon 		mediasz = sb.st_size;
593fb9cffefSMatthew Dillon 	}
594fb9cffefSMatthew Dillon 
595fb9cffefSMatthew Dillon 	/*
596fb9cffefSMatthew Dillon 	 * We require an absolute minimum of 6 sectors. One for the MBR,
597fb9cffefSMatthew Dillon 	 * 2 for the GPT header, 2 for the GPT table and one to hold some
598fb9cffefSMatthew Dillon 	 * user data. Let's catch this extreme border case here so that
599fb9cffefSMatthew Dillon 	 * we don't have to worry about it later.
600fb9cffefSMatthew Dillon 	 */
601fb9cffefSMatthew Dillon 	if (mediasz / secsz < 6) {
602fb9cffefSMatthew Dillon 		errno = ENODEV;
603fb9cffefSMatthew Dillon 		goto close;
604fb9cffefSMatthew Dillon 	}
605fb9cffefSMatthew Dillon 
606fb9cffefSMatthew Dillon 	if (verbose)
607fb9cffefSMatthew Dillon 		warnx("%s: mediasize=%llu; sectorsize=%u; blocks=%llu",
608fb9cffefSMatthew Dillon 		    device_name, (long long)mediasz, secsz,
609fb9cffefSMatthew Dillon 		    (long long)(mediasz / secsz));
610fb9cffefSMatthew Dillon 
611fb9cffefSMatthew Dillon 	map_init(mediasz / secsz);
612fb9cffefSMatthew Dillon 
613fb9cffefSMatthew Dillon 	if (gpt_mbr(fd, 0LL) == -1)
614fb9cffefSMatthew Dillon 		goto close;
615fb9cffefSMatthew Dillon 	if (gpt_gpt(fd, 1LL) == -1)
616fb9cffefSMatthew Dillon 		goto close;
617fb9cffefSMatthew Dillon 	if (gpt_gpt(fd, mediasz / secsz - 1LL) == -1)
618fb9cffefSMatthew Dillon 		goto close;
619fb9cffefSMatthew Dillon 
620fb9cffefSMatthew Dillon 	return (fd);
621fb9cffefSMatthew Dillon 
622fb9cffefSMatthew Dillon  close:
623fb9cffefSMatthew Dillon 	close(fd);
624fb9cffefSMatthew Dillon 	return (-1);
625fb9cffefSMatthew Dillon }
626fb9cffefSMatthew Dillon 
627fb9cffefSMatthew Dillon void
gpt_close(int fd)628fb9cffefSMatthew Dillon gpt_close(int fd)
629fb9cffefSMatthew Dillon {
630fb9cffefSMatthew Dillon 	/* XXX post processing? */
631fb9cffefSMatthew Dillon 	close(fd);
632fb9cffefSMatthew Dillon }
633fb9cffefSMatthew Dillon 
634d21d24f1SSascha Wildner #ifndef _LIBEFIVAR
635fb9cffefSMatthew Dillon static struct {
636fb9cffefSMatthew Dillon 	int (*fptr)(int, char *[]);
637fb9cffefSMatthew Dillon 	const char *name;
638fb9cffefSMatthew Dillon } cmdsw[] = {
639fb9cffefSMatthew Dillon 	{ cmd_add, "add" },
640210143e4SMatthew Dillon 	{ cmd_boot, "boot" },
641fb9cffefSMatthew Dillon 	{ cmd_create, "create" },
642fb9cffefSMatthew Dillon 	{ cmd_destroy, "destroy" },
64335a9ab8aSMatthew Dillon 	{ cmd_expand, "expand" },
644fb9cffefSMatthew Dillon 	{ NULL, "help" },
645bd2b9b6fSMatthew Dillon 	{ cmd_init, "init" },
646fb9cffefSMatthew Dillon 	{ cmd_label, "label" },
647fb9cffefSMatthew Dillon 	{ cmd_migrate, "migrate" },
648fb9cffefSMatthew Dillon 	{ cmd_recover, "recover" },
649fb9cffefSMatthew Dillon 	{ cmd_remove, "remove" },
650fb9cffefSMatthew Dillon 	{ NULL, "rename" },
651fb9cffefSMatthew Dillon 	{ cmd_show, "show" },
652fb9cffefSMatthew Dillon 	{ NULL, "verify" },
653fb9cffefSMatthew Dillon 	{ NULL, NULL }
654fb9cffefSMatthew Dillon };
655fb9cffefSMatthew Dillon 
656fb9cffefSMatthew Dillon static void
usage(void)657fb9cffefSMatthew Dillon usage(void)
658fb9cffefSMatthew Dillon {
659fb9cffefSMatthew Dillon 	const char *prgname = getprogname();
660fb9cffefSMatthew Dillon 
661fb9cffefSMatthew Dillon 	fprintf(stderr,
662fb9cffefSMatthew Dillon 	    "usage: %s [-rv] [-p nparts] <command> [options] <device> ...\n"
663fb9cffefSMatthew Dillon 	    "       %s show <device>\n",
664fb9cffefSMatthew Dillon 	    prgname, prgname);
665fb9cffefSMatthew Dillon 	exit(1);
666fb9cffefSMatthew Dillon }
667fb9cffefSMatthew Dillon 
668fb9cffefSMatthew Dillon static void
prefix(const char * cmd)669fb9cffefSMatthew Dillon prefix(const char *cmd)
670fb9cffefSMatthew Dillon {
671fb9cffefSMatthew Dillon 	char *pfx;
672fb9cffefSMatthew Dillon 	const char *prg;
673fb9cffefSMatthew Dillon 
674fb9cffefSMatthew Dillon 	prg = getprogname();
675fb9cffefSMatthew Dillon 	pfx = malloc(strlen(prg) + strlen(cmd) + 2);
676fb9cffefSMatthew Dillon 	/* Don't bother failing. It's not important */
677fb9cffefSMatthew Dillon 	if (pfx == NULL)
678fb9cffefSMatthew Dillon 		return;
679fb9cffefSMatthew Dillon 
680fb9cffefSMatthew Dillon 	sprintf(pfx, "%s %s", prg, cmd);
681fb9cffefSMatthew Dillon 	setprogname(pfx);
682fb9cffefSMatthew Dillon }
683fb9cffefSMatthew Dillon 
684fb9cffefSMatthew Dillon int
main(int argc,char * argv[])685fb9cffefSMatthew Dillon main(int argc, char *argv[])
686fb9cffefSMatthew Dillon {
687fb9cffefSMatthew Dillon 	char *cmd, *p;
688fb9cffefSMatthew Dillon 	int ch, i;
689fb9cffefSMatthew Dillon 
690fb9cffefSMatthew Dillon 	/* Get the generic options */
691fb9cffefSMatthew Dillon 	while ((ch = getopt(argc, argv, "p:rv")) != -1) {
692fb9cffefSMatthew Dillon 		switch(ch) {
693fb9cffefSMatthew Dillon 		case 'p':
694fb9cffefSMatthew Dillon 			if (parts > 0)
695fb9cffefSMatthew Dillon 				usage();
696fb9cffefSMatthew Dillon 			parts = strtol(optarg, &p, 10);
697fb9cffefSMatthew Dillon 			if (*p != 0 || parts < 1)
698fb9cffefSMatthew Dillon 				usage();
699fb9cffefSMatthew Dillon 			break;
700fb9cffefSMatthew Dillon 		case 'r':
701fb9cffefSMatthew Dillon 			readonly = 1;
702fb9cffefSMatthew Dillon 			break;
703fb9cffefSMatthew Dillon 		case 'v':
704fb9cffefSMatthew Dillon 			verbose++;
705fb9cffefSMatthew Dillon 			break;
706fb9cffefSMatthew Dillon 		default:
707fb9cffefSMatthew Dillon 			usage();
708fb9cffefSMatthew Dillon 		}
709fb9cffefSMatthew Dillon 	}
710fb9cffefSMatthew Dillon 	if (!parts)
711fb9cffefSMatthew Dillon 		parts = 128;
712fb9cffefSMatthew Dillon 
713fb9cffefSMatthew Dillon 	if (argc == optind)
714fb9cffefSMatthew Dillon 		usage();
715fb9cffefSMatthew Dillon 
716fb9cffefSMatthew Dillon 	cmd = argv[optind++];
717fb9cffefSMatthew Dillon 	for (i = 0; cmdsw[i].name != NULL && strcmp(cmd, cmdsw[i].name); i++);
718fb9cffefSMatthew Dillon 
719fb9cffefSMatthew Dillon 	if (cmdsw[i].fptr == NULL)
720fb9cffefSMatthew Dillon 		errx(1, "unknown command: %s", cmd);
721fb9cffefSMatthew Dillon 
722fb9cffefSMatthew Dillon 	prefix(cmd);
723fb9cffefSMatthew Dillon 	return ((*cmdsw[i].fptr)(argc, argv));
724fb9cffefSMatthew Dillon }
7254661c169SSascha Wildner #endif /* !_LIBEFIVAR */
726