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#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: src/sbin/gpt/show.c,v 1.14.2.2.6.1 2010/02/10 00:26:20 kensmith Exp $");
29
30#include <sys/types.h>
31
32#include <err.h>
33#include <stddef.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <unistd.h>
38
39#include "map.h"
40#include "gpt.h"
41
42static int show_label = 0;
43static int show_uuid = 0;
44
45static void
46usage_show(void)
47{
48
49	fprintf(stderr,
50#ifdef __APPLE__
51	    "usage: %s [-l] device ...\n", getprogname());
52#else
53	    "usage: %s [-lu] device ...\n", getprogname());
54#endif
55	exit(1);
56}
57
58static const char *
59friendly(uuid_t *t)
60{
61#ifdef __APPLE__
62	static char buf[40];
63
64	uuid_unparse(*t, buf);
65
66	return (buf);
67#else
68	static uuid_t boot = GPT_ENT_TYPE_FREEBSD_BOOT;
69	static uuid_t efi_slice = GPT_ENT_TYPE_EFI;
70	static uuid_t mslinux = GPT_ENT_TYPE_MS_BASIC_DATA;
71	static uuid_t freebsd = GPT_ENT_TYPE_FREEBSD;
72	static uuid_t hfs = GPT_ENT_TYPE_APPLE_HFS;
73	static uuid_t linuxswap = GPT_ENT_TYPE_LINUX_SWAP;
74	static uuid_t msr = GPT_ENT_TYPE_MS_RESERVED;
75	static uuid_t swap = GPT_ENT_TYPE_FREEBSD_SWAP;
76	static uuid_t ufs = GPT_ENT_TYPE_FREEBSD_UFS;
77	static uuid_t vinum = GPT_ENT_TYPE_FREEBSD_VINUM;
78	static uuid_t zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
79	static char buf[80];
80	char *s;
81
82	if (show_uuid)
83		goto unfriendly;
84
85	if (uuid_equal(t, &efi_slice, NULL))
86		return ("EFI System");
87	if (uuid_equal(t, &boot, NULL))
88		return ("FreeBSD boot");
89	if (uuid_equal(t, &swap, NULL))
90		return ("FreeBSD swap");
91	if (uuid_equal(t, &ufs, NULL))
92		return ("FreeBSD UFS/UFS2");
93	if (uuid_equal(t, &vinum, NULL))
94		return ("FreeBSD vinum");
95	if (uuid_equal(t, &zfs, NULL))
96		return ("FreeBSD ZFS");
97
98	if (uuid_equal(t, &freebsd, NULL))
99		return ("FreeBSD legacy");
100	if (uuid_equal(t, &mslinux, NULL))
101		return ("Linux/Windows");
102	if (uuid_equal(t, &linuxswap, NULL))
103		return ("Linux swap");
104	if (uuid_equal(t, &msr, NULL))
105		return ("Windows reserved");
106	if (uuid_equal(t, &hfs, NULL))
107		return ("Apple HFS");
108
109unfriendly:
110	uuid_to_string(t, &s, NULL);
111	strlcpy(buf, s, sizeof buf);
112	free(s);
113	return (buf);
114#endif
115}
116
117static void
118show(int fd __unused)
119{
120	uuid_t type;
121	off_t start;
122	map_t *m, *p;
123	struct mbr *mbr;
124	struct gpt_ent *ent;
125	unsigned int i;
126
127	printf("  %*s", lbawidth, "start");
128	printf("  %*s", lbawidth, "size");
129	printf("  index  contents\n");
130
131	m = map_first();
132	while (m != NULL) {
133		printf("  %*llu", lbawidth, (long long)m->map_start);
134		printf("  %*llu", lbawidth, (long long)m->map_size);
135		putchar(' ');
136		putchar(' ');
137		if (m->map_index > 0)
138			printf("%5d", m->map_index);
139		else
140			printf("     ");
141		putchar(' ');
142		putchar(' ');
143		switch (m->map_type) {
144		case MAP_TYPE_MBR:
145			if (m->map_start != 0)
146				printf("Extended ");
147			printf("MBR");
148			break;
149		case MAP_TYPE_PRI_GPT_HDR:
150			printf("Pri GPT header");
151			break;
152		case MAP_TYPE_SEC_GPT_HDR:
153			printf("Sec GPT header");
154			break;
155		case MAP_TYPE_PRI_GPT_TBL:
156			printf("Pri GPT table");
157			break;
158		case MAP_TYPE_SEC_GPT_TBL:
159			printf("Sec GPT table");
160			break;
161		case MAP_TYPE_MBR_PART:
162			p = m->map_data;
163			if (p->map_start != 0)
164				printf("Extended ");
165			printf("MBR part ");
166			mbr = p->map_data;
167			for (i = 0; i < 4; i++) {
168				start = le16toh(mbr->mbr_part[i].part_start_hi);
169				start = (start << 16) +
170				    le16toh(mbr->mbr_part[i].part_start_lo);
171				if (m->map_start == p->map_start + start)
172					break;
173			}
174			printf("%d", mbr->mbr_part[i].part_typ);
175			break;
176		case MAP_TYPE_GPT_PART:
177			printf("GPT part ");
178			ent = m->map_data;
179			if (show_label) {
180				printf("- \"%s\"",
181				    utf16_to_utf8(ent->ent_name));
182			} else {
183				le_uuid_dec(&ent->ent_type, &type);
184				printf("- %s", friendly(&type));
185			}
186			break;
187		case MAP_TYPE_PMBR:
188			printf("PMBR");
189			break;
190		}
191		putchar('\n');
192		m = m->map_next;
193	}
194}
195
196int
197cmd_show(int argc, char *argv[])
198{
199	int ch, fd;
200
201	readonly = 1;
202
203#ifdef __APPLE__
204	while ((ch = getopt(argc, argv, "l")) != -1) {
205#else
206	while ((ch = getopt(argc, argv, "lu")) != -1) {
207#endif
208		switch(ch) {
209		case 'l':
210			show_label = 1;
211			break;
212		case 'u':
213			show_uuid = 1;
214			break;
215		default:
216			usage_show();
217		}
218	}
219
220	if (argc == optind)
221		usage_show();
222
223	while (optind < argc) {
224		fd = gpt_open(argv[optind++]);
225		if (fd == -1) {
226			warn("unable to open device '%s'", device_name);
227			return (1);
228		}
229
230		show(fd);
231
232		gpt_close(fd);
233	}
234
235	return (0);
236}
237