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