Annotation of src/sbin/gpt/label.c, Revision 1.15
1.1 christos 1: /*-
2: * Copyright (c) 2005 Marcel Moolenaar
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: *
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: #include <sys/cdefs.h>
1.2 christos 28: #ifdef __FBSDID
1.1 christos 29: __FBSDID("$FreeBSD: src/sbin/gpt/label.c,v 1.3 2006/10/04 18:20:25 marcel Exp $");
1.2 christos 30: #endif
31: #ifdef __RCSID
1.15 ! jnemeth 32: __RCSID("$NetBSD: label.c,v 1.14 2013/11/28 01:37:14 jnemeth Exp $");
1.2 christos 33: #endif
1.1 christos 34:
35: #include <sys/types.h>
36:
37: #include <err.h>
38: #include <stddef.h>
39: #include <stdio.h>
40: #include <stdlib.h>
41: #include <string.h>
42: #include <unistd.h>
43:
44: #include "map.h"
45: #include "gpt.h"
46:
47: static int all;
48: static uuid_t type;
49: static off_t block, size;
50: static unsigned int entry;
1.15 ! jnemeth 51: static uint8_t *name, *xlabel;
1.1 christos 52:
1.5 riz 53: const char labelmsg1[] = "label -a <-l label | -f file> device ...";
1.15 ! jnemeth 54: const char labelmsg2[] = "label [-b blocknr] [-i index] [-L label] "
! 55: "[-s sectors]";
1.5 riz 56: const char labelmsg3[] = " [-t uuid] <-l label | -f file> device ...";
57:
1.8 joerg 58: __dead static void
1.1 christos 59: usage_label(void)
60: {
61: fprintf(stderr,
1.5 riz 62: "usage: %s %s\n"
63: " %s %s\n"
64: " %*s %s\n", getprogname(), labelmsg1,
1.6 dogcow 65: getprogname(), labelmsg2, (int)strlen(getprogname()), "", labelmsg3);
1.1 christos 66: exit(1);
67: }
68:
69: static void
70: label(int fd)
71: {
72: uuid_t uuid;
73: map_t *gpt, *tpg;
74: map_t *tbl, *lbt;
75: map_t *m;
76: struct gpt_hdr *hdr;
77: struct gpt_ent *ent;
78: unsigned int i;
79:
80: gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
81: if (gpt == NULL) {
82: warnx("%s: error: no primary GPT header; run create or recover",
83: device_name);
84: return;
85: }
86:
87: tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
88: if (tpg == NULL) {
89: warnx("%s: error: no secondary GPT header; run recover",
90: device_name);
91: return;
92: }
93:
94: tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
95: lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
96: if (tbl == NULL || lbt == NULL) {
97: warnx("%s: error: run recover -- trust me", device_name);
98: return;
99: }
100:
101: /* Relabel all matching entries in the map. */
102: for (m = map_first(); m != NULL; m = m->map_next) {
103: if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
104: continue;
105: if (entry > 0 && entry != m->map_index)
106: continue;
107: if (block > 0 && block != m->map_start)
108: continue;
109: if (size > 0 && size != m->map_size)
110: continue;
111:
112: i = m->map_index - 1;
113:
114: hdr = gpt->map_data;
115: ent = (void*)((char*)tbl->map_data + i *
116: le32toh(hdr->hdr_entsz));
1.15 ! jnemeth 117:
! 118: if (xlabel != NULL)
! 119: if (strcmp((char *)xlabel,
! 120: (char *)utf16_to_utf8(ent->ent_name)) != 0)
! 121: continue;
! 122:
1.10 jakllsch 123: le_uuid_dec(ent->ent_type, &uuid);
1.1 christos 124: if (!uuid_is_nil(&type, NULL) &&
125: !uuid_equal(&type, &uuid, NULL))
126: continue;
127:
128: /* Label the primary entry. */
129: utf8_to_utf16(name, ent->ent_name, 36);
130:
131: hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
132: le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
133: hdr->hdr_crc_self = 0;
134: hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
135:
136: gpt_write(fd, gpt);
137: gpt_write(fd, tbl);
138:
139: hdr = tpg->map_data;
140: ent = (void*)((char*)lbt->map_data + i *
141: le32toh(hdr->hdr_entsz));
142:
1.9 jakllsch 143: /* Label the secondary entry. */
1.1 christos 144: utf8_to_utf16(name, ent->ent_name, 36);
145:
146: hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
147: le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
148: hdr->hdr_crc_self = 0;
149: hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
150:
151: gpt_write(fd, lbt);
152: gpt_write(fd, tpg);
153:
1.7 dyoung 154: printf("partition %d on %s labeled %s\n", m->map_index,
1.2 christos 155: device_name, name);
1.1 christos 156: }
157: }
158:
159: static void
160: name_from_file(const char *fn)
161: {
162: FILE *f;
163: char *p;
164: size_t maxlen = 1024;
165: size_t len;
166:
167: if (strcmp(fn, "-") != 0) {
168: f = fopen(fn, "r");
169: if (f == NULL)
170: err(1, "unable to open file %s", fn);
171: } else
172: f = stdin;
173: name = malloc(maxlen);
174: len = fread(name, 1, maxlen - 1, f);
175: if (ferror(f))
176: err(1, "unable to read label from file %s", fn);
177: if (f != stdin)
178: fclose(f);
179: name[len] = '\0';
180: /* Only keep the first line, excluding the newline character. */
1.3 christos 181: p = strchr((const char *)name, '\n');
1.1 christos 182: if (p != NULL)
183: *p = '\0';
184: }
185:
186: int
187: cmd_label(int argc, char *argv[])
188: {
189: char *p;
190: int ch, fd;
1.12 jnemeth 191: int64_t human_num;
1.1 christos 192:
193: /* Get the label options */
1.15 ! jnemeth 194: while ((ch = getopt(argc, argv, "ab:f:i:L:l:s:t:")) != -1) {
1.1 christos 195: switch(ch) {
196: case 'a':
197: if (all > 0)
198: usage_label();
199: all = 1;
200: break;
201: case 'b':
202: if (block > 0)
203: usage_label();
1.12 jnemeth 204: if (dehumanize_number(optarg, &human_num) < 0)
1.1 christos 205: usage_label();
1.12 jnemeth 206: block = human_num;
1.14 jnemeth 207: if (block < 1)
208: usage_label();
1.1 christos 209: break;
210: case 'f':
211: if (name != NULL)
212: usage_label();
213: name_from_file(optarg);
214: break;
215: case 'i':
216: if (entry > 0)
217: usage_label();
1.4 riz 218: entry = strtoul(optarg, &p, 10);
1.1 christos 219: if (*p != 0 || entry < 1)
220: usage_label();
221: break;
1.15 ! jnemeth 222: case 'L':
! 223: if (xlabel != NULL)
! 224: usage_label();
! 225: xlabel = (uint8_t *)strdup(optarg);
! 226: break;
1.1 christos 227: case 'l':
228: if (name != NULL)
229: usage_label();
1.3 christos 230: name = (uint8_t *)strdup(optarg);
1.1 christos 231: break;
232: case 's':
233: if (size > 0)
234: usage_label();
235: size = strtoll(optarg, &p, 10);
236: if (*p != 0 || size < 1)
237: usage_label();
238: break;
239: case 't':
240: if (!uuid_is_nil(&type, NULL))
241: usage_label();
242: if (parse_uuid(optarg, &type) != 0)
243: usage_label();
244: break;
245: default:
246: usage_label();
247: }
248: }
249:
250: if (!all ^
1.15 ! jnemeth 251: (block > 0 || entry > 0 || xlabel != NULL || size > 0 ||
! 252: !uuid_is_nil(&type, NULL)))
1.1 christos 253: usage_label();
254:
255: if (name == NULL || argc == optind)
256: usage_label();
257:
258: while (optind < argc) {
259: fd = gpt_open(argv[optind++]);
260: if (fd == -1) {
261: warn("unable to open device '%s'", device_name);
262: continue;
263: }
264:
265: label(fd);
266:
267: gpt_close(fd);
268: }
269:
270: return (0);
271: }
CVSweb <webmaster@jp.NetBSD.org>