| /*- |
| * Copyright (c) 2002 Marcel Moolenaar |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef LINUX |
| #include <sys/cdefs.h> |
| __FBSDID("$FreeBSD$"); |
| #endif |
| |
| #include <sys/types.h> |
| |
| #include <err.h> |
| #include <stddef.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| #include "map.h" |
| #include "gpt.h" |
| |
| static int show_label = 0; |
| static int show_uuid = 0; |
| |
| static void |
| usage_show(void) |
| { |
| |
| fprintf(stderr, |
| "usage: %s [-lu] device ...\n", getprogname()); |
| exit(1); |
| } |
| |
| static const char * |
| friendly(uuid_t *t) |
| { |
| static uuid_t boot = GPT_ENT_TYPE_FREEBSD_BOOT; |
| static uuid_t efi_slice = GPT_ENT_TYPE_EFI; |
| static uuid_t mslinux = GPT_ENT_TYPE_MS_BASIC_DATA; |
| static uuid_t freebsd = GPT_ENT_TYPE_FREEBSD; |
| static uuid_t hfs = GPT_ENT_TYPE_APPLE_HFS; |
| static uuid_t linuxswap = GPT_ENT_TYPE_LINUX_SWAP; |
| static uuid_t msr = GPT_ENT_TYPE_MS_RESERVED; |
| static uuid_t swap = GPT_ENT_TYPE_FREEBSD_SWAP; |
| static uuid_t ufs = GPT_ENT_TYPE_FREEBSD_UFS; |
| static uuid_t vinum = GPT_ENT_TYPE_FREEBSD_VINUM; |
| static uuid_t zfs = GPT_ENT_TYPE_FREEBSD_ZFS; |
| static uuid_t chrome_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL; |
| static uuid_t chrome_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS; |
| static uuid_t chrome_future = GPT_ENT_TYPE_CHROMEOS_RESERVED; |
| static char buf[80]; |
| char *s; |
| |
| if (show_uuid) |
| goto unfriendly; |
| |
| if (uuid_equal(t, &efi_slice, NULL)) |
| return ("EFI System"); |
| if (uuid_equal(t, &boot, NULL)) |
| return ("FreeBSD boot"); |
| if (uuid_equal(t, &swap, NULL)) |
| return ("FreeBSD swap"); |
| if (uuid_equal(t, &ufs, NULL)) |
| return ("FreeBSD UFS/UFS2"); |
| if (uuid_equal(t, &vinum, NULL)) |
| return ("FreeBSD vinum"); |
| if (uuid_equal(t, &zfs, NULL)) |
| return ("FreeBSD ZFS"); |
| |
| if (uuid_equal(t, &freebsd, NULL)) |
| return ("FreeBSD legacy"); |
| if (uuid_equal(t, &mslinux, NULL)) |
| return ("Linux/Windows"); |
| if (uuid_equal(t, &linuxswap, NULL)) |
| return ("Linux swap"); |
| if (uuid_equal(t, &msr, NULL)) |
| return ("Windows reserved"); |
| if (uuid_equal(t, &hfs, NULL)) |
| return ("Apple HFS"); |
| if (uuid_equal(t, &chrome_kernel, NULL)) |
| return ("Chrome OS kernel"); |
| if (uuid_equal(t, &chrome_rootfs, NULL)) |
| return ("Chrome OS rootfs"); |
| if (uuid_equal(t, &chrome_future, NULL)) |
| return ("Chrome OS reserved"); |
| |
| unfriendly: |
| uuid_to_string(t, &s, NULL); |
| strlcpy(buf, s, sizeof buf); |
| free(s); |
| return (buf); |
| } |
| |
| static void |
| show(int fd __unused) |
| { |
| uuid_t type; |
| off_t start; |
| map_t *m, *p; |
| struct mbr *mbr; |
| struct gpt_ent *ent; |
| unsigned int i; |
| |
| printf(" %*s", lbawidth, "start"); |
| printf(" %*s", lbawidth, "size"); |
| printf(" index contents\n"); |
| |
| m = map_first(); |
| while (m != NULL) { |
| printf(" %*llu", lbawidth, (long long)m->map_start); |
| printf(" %*llu", lbawidth, (long long)m->map_size); |
| putchar(' '); |
| putchar(' '); |
| if (m->map_index > 0) |
| printf("%5d", m->map_index); |
| else |
| printf(" "); |
| putchar(' '); |
| putchar(' '); |
| switch (m->map_type) { |
| case MAP_TYPE_MBR: |
| if (m->map_start != 0) |
| printf("Extended "); |
| printf("MBR"); |
| break; |
| case MAP_TYPE_PRI_GPT_HDR: |
| printf("Pri GPT header"); |
| break; |
| case MAP_TYPE_SEC_GPT_HDR: |
| printf("Sec GPT header"); |
| break; |
| case MAP_TYPE_PRI_GPT_TBL: |
| printf("Pri GPT table"); |
| break; |
| case MAP_TYPE_SEC_GPT_TBL: |
| printf("Sec GPT table"); |
| break; |
| case MAP_TYPE_MBR_PART: |
| p = m->map_data; |
| if (p->map_start != 0) |
| printf("Extended "); |
| printf("MBR part "); |
| mbr = p->map_data; |
| for (i = 0; i < 4; i++) { |
| start = le16toh(mbr->mbr_part[i].part_start_hi); |
| start = (start << 16) + |
| le16toh(mbr->mbr_part[i].part_start_lo); |
| if (m->map_start == p->map_start + start) |
| break; |
| } |
| printf("%d", mbr->mbr_part[i].part_typ); |
| break; |
| case MAP_TYPE_GPT_PART: |
| printf("GPT part "); |
| ent = m->map_data; |
| if (show_label) { |
| printf("- \"%s\"", |
| utf16_to_utf8(ent->ent_name)); |
| } else { |
| le_uuid_dec(&ent->ent_type, &type); |
| printf("- %s", friendly(&type)); |
| } |
| |
| /* Show the uuid of each partition. */ |
| { |
| char *s; |
| uuid_to_string(&ent->ent_uuid, &s, NULL); |
| printf(" (ID: %s)", s); |
| free(s); |
| } |
| break; |
| case MAP_TYPE_PMBR: |
| mbr = m->map_data; |
| if (le16toh(mbr->magic_number) == MBR_MAGIC) |
| { |
| char *s; |
| uuid_to_string(&mbr->boot_guid, &s, NULL); |
| printf("PMBR (Boot GUID: %s)", s); |
| free(s); |
| } |
| else |
| { |
| printf("PMBR (no magic)"); |
| } |
| break; |
| } |
| putchar('\n'); |
| m = m->map_next; |
| } |
| } |
| |
| int |
| cmd_show(int argc, char *argv[]) |
| { |
| int ch, fd; |
| |
| while ((ch = getopt(argc, argv, "lu")) != -1) { |
| switch(ch) { |
| case 'l': |
| show_label = 1; |
| break; |
| case 'u': |
| show_uuid = 1; |
| break; |
| default: |
| usage_show(); |
| } |
| } |
| |
| if (argc == optind) |
| usage_show(); |
| |
| while (optind < argc) { |
| fd = gpt_open(argv[optind++]); |
| if (fd == -1) { |
| warn("unable to open device '%s'", device_name); |
| continue; |
| } |
| |
| show(fd); |
| |
| gpt_close(fd); |
| } |
| |
| return (0); |
| } |