1239070Sae/*- 2239070Sae * Copyright (c) 2012 Andrey V. Elsukov <ae@FreeBSD.org> 3239070Sae * All rights reserved. 4239070Sae * 5239070Sae * Redistribution and use in source and binary forms, with or without 6239070Sae * modification, are permitted provided that the following conditions 7239070Sae * are met: 8239070Sae * 1. Redistributions of source code must retain the above copyright 9239070Sae * notice, this list of conditions and the following disclaimer. 10239070Sae * 2. Redistributions in binary form must reproduce the above copyright 11239070Sae * notice, this list of conditions and the following disclaimer in the 12239070Sae * documentation and/or other materials provided with the distribution. 13239070Sae * 14239070Sae * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15239070Sae * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16239070Sae * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17239070Sae * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18239070Sae * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19239070Sae * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20239070Sae * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21239070Sae * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22239070Sae * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23239070Sae * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24239070Sae * SUCH DAMAGE. 25239070Sae */ 26239070Sae 27239070Sae#include <sys/cdefs.h> 28239070Sae__FBSDID("$FreeBSD$"); 29239070Sae 30239070Sae#include <sys/types.h> 31239070Sae#include <sys/stat.h> 32239070Sae 33239070Sae#include <err.h> 34239070Sae#include <fcntl.h> 35239070Sae#include <libgeom.h> 36239070Sae#include <libutil.h> 37239070Sae#include <part.h> 38239070Sae#include <stdio.h> 39239070Sae#include <unistd.h> 40239070Sae 41239070Saestruct disk { 42239070Sae const char *name; 43239070Sae uint64_t mediasize; 44239070Sae uint16_t sectorsize; 45239070Sae 46239070Sae int fd; 47239070Sae int file; 48239070Sae off_t offset; 49239070Sae}; 50239070Sae 51239070Saestatic int 52239070Saediskread(void *arg, void *buf, size_t blocks, off_t offset) 53239070Sae{ 54239070Sae struct disk *dp; 55239070Sae 56239070Sae dp = (struct disk *)arg; 57254333Sae printf("%s: read %lu blocks from the offset %jd [+%jd]\n", dp->name, 58243244Sae blocks, offset, dp->offset); 59239070Sae if (offset >= dp->mediasize / dp->sectorsize) 60239070Sae return (-1); 61239070Sae 62239070Sae return (pread(dp->fd, buf, blocks * dp->sectorsize, 63239070Sae (offset + dp->offset) * dp->sectorsize) != blocks * dp->sectorsize); 64239070Sae} 65239070Sae 66239070Saestatic const char* 67239070Saeptable_type2str(const struct ptable *table) 68239070Sae{ 69239070Sae 70239070Sae switch (ptable_gettype(table)) { 71239070Sae case PTABLE_NONE: 72239070Sae return ("None"); 73239070Sae case PTABLE_BSD: 74239070Sae return ("BSD"); 75239070Sae case PTABLE_MBR: 76239070Sae return ("MBR"); 77239070Sae case PTABLE_GPT: 78239070Sae return ("GPT"); 79239070Sae case PTABLE_VTOC8: 80239070Sae return ("VTOC8"); 81239070Sae }; 82239070Sae return ("Unknown"); 83239070Sae} 84239070Sae 85239070Sae#define PWIDTH 35 86239070Saestatic void 87239070Saeptable_print(void *arg, const char *pname, const struct ptable_entry *part) 88239070Sae{ 89239070Sae struct ptable *table; 90239070Sae struct disk *dp, bsd; 91239070Sae char line[80], size[6]; 92239070Sae 93239070Sae dp = (struct disk *)arg; 94239070Sae sprintf(line, " %s%s: %s", dp->file ? "disk0": dp->name, pname, 95239070Sae parttype2str(part->type)); 96239070Sae humanize_number(size, sizeof(size), 97239070Sae (part->end - part->start + 1) * dp->sectorsize, "", 98239070Sae HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 99239070Sae printf("%-*s%s\n", PWIDTH, line, size); 100239070Sae if (part->type == PART_FREEBSD) { 101239070Sae sprintf(line, "%s%s", dp->file ? "disk0": dp->name, pname); 102239070Sae bsd.name = line; 103239070Sae bsd.fd = dp->fd; 104239070Sae bsd.file = 0; /* to use dp->name in the next sprintf */ 105239070Sae bsd.offset = dp->offset + part->start; 106239070Sae bsd.sectorsize = dp->sectorsize; 107239070Sae bsd.mediasize = (part->end - part->start + 1) * dp->sectorsize; 108239070Sae table = ptable_open(&bsd, bsd.mediasize / bsd.sectorsize, 109239070Sae bsd.sectorsize, diskread); 110239070Sae if (table == NULL) 111239070Sae return; 112239070Sae ptable_iterate(table, &bsd, ptable_print); 113239070Sae ptable_close(table); 114239070Sae } 115239070Sae} 116239070Sae#undef PWIDTH 117239070Sae 118239070Saestatic void 119239070Saeinspect_disk(struct disk *dp) 120239070Sae{ 121239070Sae struct ptable *table; 122239070Sae 123239070Sae table = ptable_open(dp, dp->mediasize / dp->sectorsize, 124239070Sae dp->sectorsize, diskread); 125239070Sae if (table == NULL) { 126239070Sae printf("ptable_open failed\n"); 127239070Sae return; 128239070Sae } 129239070Sae printf("Partition table detected: %s\n", ptable_type2str(table)); 130239070Sae ptable_iterate(table, dp, ptable_print); 131239070Sae ptable_close(table); 132239070Sae} 133239070Sae 134239070Saeint 135239070Saemain(int argc, char **argv) 136239070Sae{ 137239070Sae struct stat sb; 138239070Sae struct disk d; 139239070Sae 140239070Sae if (argc < 2) 141239070Sae errx(1, "Usage: %s <GEOM provider name> | " 142239070Sae "<disk image file name>", argv[0]); 143239070Sae d.name = argv[1]; 144239070Sae if (stat(d.name, &sb) == 0 && S_ISREG(sb.st_mode)) { 145239070Sae d.fd = open(d.name, O_RDONLY); 146239070Sae if (d.fd < 0) 147239070Sae err(1, "open %s", d.name); 148239070Sae d.mediasize = sb.st_size; 149239070Sae d.sectorsize = 512; 150239070Sae d.file = 1; 151239070Sae } else { 152239070Sae d.fd = g_open(d.name, 0); 153239070Sae if (d.fd < 0) 154239070Sae err(1, "g_open %s", d.name); 155239070Sae d.mediasize = g_mediasize(d.fd); 156239070Sae d.sectorsize = g_sectorsize(d.fd); 157239070Sae d.file = 0; 158239070Sae } 159239070Sae d.offset = 0; 160239070Sae printf("%s \"%s\" opened\n", d.file ? "Disk image": "GEOM provider", 161239070Sae d.name); 162239070Sae printf("Mediasize: %ju Bytes (%ju sectors)\nSectorsize: %u Bytes\n", 163239070Sae d.mediasize, d.mediasize / d.sectorsize, d.sectorsize); 164239070Sae 165239070Sae inspect_disk(&d); 166239070Sae 167239070Sae if (d.file) 168239070Sae close(d.fd); 169239070Sae else 170239070Sae g_close(d.fd); 171239070Sae return (0); 172239070Sae} 173