show.c revision 1.37
1/*-
2 * Copyright (c) 2002 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#if HAVE_NBTOOL_CONFIG_H
28#include "nbtool_config.h"
29#endif
30
31#include <sys/cdefs.h>
32#ifdef __FBSDID
33__FBSDID("$FreeBSD: src/sbin/gpt/show.c,v 1.14 2006/06/22 22:22:32 marcel Exp $");
34#endif
35#ifdef __RCSID
36__RCSID("$NetBSD: show.c,v 1.37 2016/06/09 15:12:54 christos Exp $");
37#endif
38
39#include <sys/types.h>
40
41#include <err.h>
42#include <stddef.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <unistd.h>
47
48#include "map.h"
49#include "gpt.h"
50#include "gpt_private.h"
51
52static int cmd_show(gpt_t, int, char *[]);
53
54static const char *showhelp[] = {
55	"[-aglu] [-i index]",
56};
57
58#define SHOW_UUID  1
59#define SHOW_GUID  2
60#define SHOW_LABEL 4
61#define SHOW_ALL   8
62
63struct gpt_cmd c_show = {
64	"show",
65	cmd_show,
66	showhelp, __arraycount(showhelp),
67	GPT_READONLY,
68};
69
70#define usage() gpt_usage(NULL, &c_show)
71
72static void
73print_part_type(int map_type, int flags, void *map_data, off_t map_start)
74{
75	off_t start;
76	map_t p;
77	struct mbr *mbr;
78	struct gpt_ent *ent;
79	unsigned int i;
80	char buf[128], *b = buf;
81	uint8_t utfbuf[__arraycount(ent->ent_name) * 3 + 1];
82
83	switch (map_type) {
84	case MAP_TYPE_UNUSED:
85		printf("Unused");
86		break;
87	case MAP_TYPE_MBR:
88		if (map_start != 0)
89			printf("Extended ");
90		printf("MBR");
91		break;
92	case MAP_TYPE_PRI_GPT_HDR:
93		printf("Pri GPT header");
94		break;
95	case MAP_TYPE_SEC_GPT_HDR:
96		printf("Sec GPT header");
97		break;
98	case MAP_TYPE_PRI_GPT_TBL:
99		printf("Pri GPT table");
100		break;
101	case MAP_TYPE_SEC_GPT_TBL:
102		printf("Sec GPT table");
103		break;
104	case MAP_TYPE_MBR_PART:
105		p = map_data;
106		if (p->map_start != 0)
107			printf("Extended ");
108		printf("MBR part ");
109		mbr = p->map_data;
110		for (i = 0; i < 4; i++) {
111			start = le16toh(mbr->mbr_part[i].part_start_hi);
112			start = (start << 16) +
113			    le16toh(mbr->mbr_part[i].part_start_lo);
114			if (map_start == p->map_start + start)
115				break;
116		}
117		if (i == 4) {
118			/* wasn't there */
119			printf("[partition not found?]");
120		} else {
121			printf("%d%s", mbr->mbr_part[i].part_typ,
122			    mbr->mbr_part[i].part_flag == 0x80 ?
123			    " (active)" : "");
124		}
125		break;
126	case MAP_TYPE_GPT_PART:
127		printf("GPT part ");
128		ent = map_data;
129		if (flags & SHOW_LABEL) {
130			utf16_to_utf8(ent->ent_name, utfbuf,
131			    sizeof(utfbuf));
132			b = (char *)utfbuf;
133		} else if (flags & SHOW_GUID) {
134			gpt_uuid_snprintf( buf, sizeof(buf), "%d",
135			    ent->ent_guid);
136		} else if (flags & SHOW_UUID) {
137			gpt_uuid_snprintf(buf, sizeof(buf),
138			    "%d", ent->ent_type);
139		} else {
140			gpt_uuid_snprintf(buf, sizeof(buf), "%ls",
141			    ent->ent_type);
142		}
143		printf("- %s", b);
144		break;
145	case MAP_TYPE_PMBR:
146		printf("PMBR");
147		break;
148	default:
149		printf("Unknown %#x", map_type);
150		break;
151	}
152}
153
154static int
155show(gpt_t gpt, int show)
156{
157	map_t m;
158
159	printf("  %*s", gpt->lbawidth, "start");
160	printf("  %*s", gpt->lbawidth, "size");
161	printf("  index  contents\n");
162
163	m = map_first(gpt);
164	while (m != NULL) {
165		printf("  %*llu", gpt->lbawidth, (long long)m->map_start);
166		printf("  %*llu", gpt->lbawidth, (long long)m->map_size);
167		putchar(' ');
168		putchar(' ');
169		if (m->map_index > 0)
170			printf("%5d", m->map_index);
171		else
172			printf("     ");
173		putchar(' ');
174		putchar(' ');
175		print_part_type(m->map_type, show, m->map_data, m->map_start);
176		putchar('\n');
177		m = m->map_next;
178	}
179	return 0;
180}
181
182static int
183show_one(gpt_t gpt, unsigned int entry)
184{
185	map_t m;
186	struct gpt_ent *ent;
187	char s1[128], s2[128];
188	uint8_t utfbuf[__arraycount(ent->ent_name) * 3 + 1];
189
190	for (m = map_first(gpt); m != NULL; m = m->map_next)
191		if (entry == m->map_index)
192			break;
193	if (m == NULL) {
194		gpt_warnx(gpt, "Could not find index %d", entry);
195		return -1;
196	}
197	ent = m->map_data;
198
199	printf("Details for index %d:\n", entry);
200	gpt_show_num("Start", (uintmax_t)(m->map_start * gpt->secsz));
201	gpt_show_num("Size", (uintmax_t)(m->map_size * gpt->secsz));
202
203	gpt_uuid_snprintf(s1, sizeof(s1), "%s", ent->ent_type);
204	gpt_uuid_snprintf(s2, sizeof(s2), "%d", ent->ent_type);
205	if (strcmp(s1, s2) == 0)
206		strlcpy(s1, "unknown", sizeof(s1));
207	printf("Type: %s (%s)\n", s1, s2);
208
209	gpt_uuid_snprintf(s2, sizeof(s1), "%d", ent->ent_guid);
210	printf("GUID: %s\n", s2);
211
212	utf16_to_utf8(ent->ent_name, utfbuf, sizeof(utfbuf));
213	printf("Label: %s\n", (char *)utfbuf);
214
215	printf("Attributes: ");
216	if (ent->ent_attr == 0) {
217		printf("None\n");
218	} else  {
219		char buf[1024];
220		printf("%s\n", gpt_attr_list(buf, sizeof(buf), ent->ent_attr));
221	}
222
223	return 0;
224}
225
226static int
227show_all(gpt_t gpt)
228{
229	map_t m;
230	struct gpt_ent *ent;
231	char s1[128], s2[128];
232#ifdef HN_AUTOSCALE
233	char human_num[8];
234#endif
235	uint8_t utfbuf[__arraycount(ent->ent_name) * 3 + 1];
236#define PFX "                                 "
237
238	printf("  %*s", gpt->lbawidth, "start");
239	printf("  %*s", gpt->lbawidth, "size");
240	printf("  index  contents\n");
241
242	m = map_first(gpt);
243	while (m != NULL) {
244		printf("  %*llu", gpt->lbawidth, (long long)m->map_start);
245		printf("  %*llu", gpt->lbawidth, (long long)m->map_size);
246		putchar(' ');
247		putchar(' ');
248		if (m->map_index > 0) {
249			printf("%5d  ", m->map_index);
250			print_part_type(m->map_type, 0, m->map_data,
251			    m->map_start);
252			putchar('\n');
253
254			ent = m->map_data;
255
256			gpt_uuid_snprintf(s1, sizeof(s1), "%s", ent->ent_type);
257			gpt_uuid_snprintf(s2, sizeof(s2), "%d", ent->ent_type);
258			if (strcmp(s1, s2) == 0)
259				strlcpy(s1, "unknown", sizeof(s1));
260			printf(PFX "Type: %s\n", s1);
261			printf(PFX "TypeID: %s\n", s2);
262
263			gpt_uuid_snprintf(s2, sizeof(s1), "%d", ent->ent_guid);
264			printf(PFX "GUID: %s\n", s2);
265
266			printf(PFX "Size: ");
267#ifdef HN_AUTOSCALE
268			if (humanize_number(human_num, sizeof(human_num),
269			    (int64_t)(m->map_size * gpt->secsz),
270			    "", HN_AUTOSCALE, HN_B) < 0) {
271#endif
272				printf("%ju",
273				    (int64_t)(m->map_size * gpt->secsz));
274#ifdef HN_AUTOSCALE
275			} else {
276				printf("%s", human_num);
277			}
278#endif
279			putchar('\n');
280
281			utf16_to_utf8(ent->ent_name, utfbuf, sizeof(utfbuf));
282			printf(PFX "Label: %s\n", (char *)utfbuf);
283
284			printf(PFX "Attributes: ");
285			if (ent->ent_attr == 0) {
286				printf("None\n");
287			} else  {
288				char buf[1024];
289
290				printf("%s\n", gpt_attr_list(buf, sizeof(buf),
291				    ent->ent_attr));
292			}
293		} else {
294			printf("       ");
295			print_part_type(m->map_type, 0, m->map_data,
296			    m->map_start);
297			putchar('\n');
298		}
299		m = m->map_next;
300	}
301	return 0;
302}
303
304static int
305cmd_show(gpt_t gpt, int argc, char *argv[])
306{
307	int ch;
308	int xshow = 0;
309	unsigned int entry = 0;
310
311	while ((ch = getopt(argc, argv, "gi:lua")) != -1) {
312		switch(ch) {
313		case 'a':
314			xshow |= SHOW_ALL;
315			break;
316		case 'g':
317			xshow |= SHOW_GUID;
318			break;
319		case 'i':
320			if (gpt_uint_get(gpt, &entry) == -1)
321				return usage();
322			break;
323		case 'l':
324			xshow |= SHOW_LABEL;
325			break;
326		case 'u':
327			xshow |= SHOW_UUID;
328			break;
329		default:
330			return usage();
331		}
332	}
333
334	if (argc != optind)
335		return usage();
336
337	if (xshow & SHOW_ALL)
338		return show_all(gpt);
339
340	return entry > 0 ? show_one(gpt, entry) : show(gpt, xshow);
341}
342