diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2001-03-24 00:14:39 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2001-03-24 00:14:39 +0000 |
commit | ffb72f990c9933280de104024acf91acee02c1a5 (patch) | |
tree | 8312fd465c763b17886e6e1795ab48bde45c2381 /sbin/pdisk/dump.c | |
parent | fa5275b22eb94a7d990e643d54768420845d618c (diff) |
Import of pdisk from apple, BSD licensed code. Archive dated Feb 18 1998
This is a HFS partition editing tool.
Diffstat (limited to 'sbin/pdisk/dump.c')
-rw-r--r-- | sbin/pdisk/dump.c | 804 |
1 files changed, 804 insertions, 0 deletions
diff --git a/sbin/pdisk/dump.c b/sbin/pdisk/dump.c new file mode 100644 index 00000000000..7c326c824c0 --- /dev/null +++ b/sbin/pdisk/dump.c @@ -0,0 +1,804 @@ +// +// dump.c - dumping partition maps +// +// Written by Eryk Vershen (eryk@apple.com) +// + +/* + * Copyright 1996,1997,1998 by Apple Computer, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +// for *printf() +#include <stdio.h> + +// for malloc() & free() +#ifndef __linux__ +#include <stdlib.h> +//#include <unistd.h> +#else +#include <malloc.h> +#endif + +// for strcmp() +#include <string.h> +// for O_RDONLY +#include <fcntl.h> +// for errno +#include <errno.h> + +#include "dump.h" +#include "pathname.h" +#include "io.h" +#include "errors.h" + + +// +// Defines +// +#if DPISTRLEN != 32 +#error Change in strlen in partition entries! Fix constants +#endif + +#define get_align_long(x) (*(x)) + + +// +// Types +// +typedef struct names { + char *abbr; + char *full; +} NAMES; + + +// +// Global Constants +// +NAMES plist[] = { + {"Drvr", "Apple_Driver"}, + {"Free", "Apple_Free"}, + {" HFS", "Apple_HFS"}, + {" MFS", "Apple_MFS"}, + {"PDOS", "Apple_PRODOS"}, + {"junk", "Apple_Scratch"}, + {"unix", "Apple_UNIX_SVR2"}, + {" map", "Apple_partition_map"}, + {0, 0}, +}; + +const char * kStringEmpty = ""; +const char * kStringNot = " not"; + + +// +// Global Variables +// +int aflag = AFLAG_DEFAULT; /* abbreviate partition types */ +int pflag = PFLAG_DEFAULT; /* show physical limits of partition */ + + +// +// Forward declarations +// +void adjust_value_and_compute_prefix(double *value, int *prefix); +void dump_block_zero(partition_map_header *map); +void dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits); +int get_max_base_or_length(partition_map_header *map); +int get_max_name_string_length(partition_map_header *map); +int get_max_type_string_length(partition_map_header *map); +int strnlen(char *s, int n); + + +// +// Routines +// +int +dump(char *name) +{ + partition_map_header *map; + int junk; + + map = open_partition_map(name, &junk, 0); + if (map == NULL) { + //error(-1, "No partition map in '%s'", name); + return 0; + } + + dump_partition_map(map, 1); + + close_partition_map(map); + + return 1; +} + + +void +dump_block_zero(partition_map_header *map) +{ + Block0 *p; + DDMap *m; + int i; + double value; + int prefix; + + p = map->misc; + if (p->sbSig != BLOCK0_SIGNATURE) { + return; + } + + value = ((double)p->sbBlkCount) * p->sbBlkSize; + adjust_value_and_compute_prefix(&value, &prefix); + printf("\nDevice block size=%u, Number of Blocks=%lu (%1.1f%c)\n", + p->sbBlkSize, p->sbBlkCount, value, prefix); + + printf("DeviceType=0x%x, DeviceId=0x%x\n", + p->sbDevType, p->sbDevId); + if (p->sbDrvrCount > 0) { + printf("Drivers-\n"); + m = (DDMap *) p->sbMap; + for (i = 0; i < p->sbDrvrCount; i++) { + printf("%u: @ %lu for %u, type=0x%x\n", i+1, + get_align_long(&m[i].ddBlock), + m[i].ddSize, m[i].ddType); + } + } + printf("\n"); +} + + +void +dump_partition_map(partition_map_header *map, int disk_order) +{ + partition_map * entry; + int max_type_length; + int max_name_length; + int digits; + char *alternate; + + if (map == NULL) { + bad_input("No partition map exists"); + return; + } + alternate = get_mklinux_name(map->name); + if (alternate) { + printf("\nPartition map (with %d byte blocks) on '%s' (%s)\n", + map->logical_block, map->name, alternate); + free(alternate); + } else { + printf("\nPartition map (with %d byte blocks) on '%s'\n", + map->logical_block, map->name); + } + + digits = number_of_digits(get_max_base_or_length(map)); + if (digits < 6) { + digits = 6; + } + if (aflag) { + max_type_length = 4; + } else { + max_type_length = get_max_type_string_length(map); + if (max_type_length < 4) { + max_type_length = 4; + } + } + max_name_length = get_max_name_string_length(map); + if (max_name_length < 6) { + max_name_length = 6; + } + printf(" #: %*s %-*s %*s %-*s ( size )\n", + max_type_length, "type", + max_name_length, "name", + digits, "length", digits, "base"); + + if (disk_order) { + for (entry = map->disk_order; entry != NULL; + entry = entry->next_on_disk) { + + dump_partition_entry(entry, max_type_length, max_name_length, digits); + } + } else { + for (entry = map->base_order; entry != NULL; + entry = entry->next_by_base) { + + dump_partition_entry(entry, max_type_length, max_name_length, digits); + } + } + dump_block_zero(map); +} + + +void +dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits) +{ + partition_map_header *map; + int j; + DPME *p; + char *s; + u32 size; + double bytes; + int driver; + + map = entry->the_map; + p = entry->data; + driver = entry->contains_driver? '*': ' '; + if (aflag) { + s = "????"; + for (j = 0; plist[j].abbr != 0; j++) { + if (strcmp(p->dpme_type, plist[j].full) == 0) { + s = plist[j].abbr; + break; + } + } + printf("%2ld: %.4s%c%-*.32s ", + entry->disk_address, s, driver, name_length, p->dpme_name); + } else { + printf("%2ld: %*.32s%c%-*.32s ", + entry->disk_address, type_length, p->dpme_type, + driver, name_length, p->dpme_name); + } + + if (pflag) { + printf("%*lu ", digits, p->dpme_pblocks); + size = p->dpme_pblocks; + } else if (p->dpme_lblocks + p->dpme_lblock_start != p->dpme_pblocks) { + printf("%*lu+", digits, p->dpme_lblocks); + size = p->dpme_lblocks; + } else if (p->dpme_lblock_start != 0) { + printf("%*lu ", digits, p->dpme_lblocks); + size = p->dpme_lblocks; + } else { + printf("%*lu ", digits, p->dpme_pblocks); + size = p->dpme_pblocks; + } + if (pflag || p->dpme_lblock_start == 0) { + printf("@ %-*lu", digits, p->dpme_pblock_start); + } else { + printf("@~%-*lu", digits, p->dpme_pblock_start + p->dpme_lblock_start); + } + + bytes = ((double)size) * map->logical_block; + adjust_value_and_compute_prefix(&bytes, &j); + if (j != ' ' && j != 'K') { + printf(" (%#5.1f%c)", bytes, j); + } + +#if 0 + // Old A/UX fields that no one pays attention to anymore. + bp = (BZB *) (p->dpme_bzb); + j = -1; + if (bp->bzb_magic == BZBMAGIC) { + switch (bp->bzb_type) { + case FSTEFS: + s = "EFS"; + break; + case FSTSFS: + s = "SFS"; + j = 1; + break; + case FST: + default: + if (bzb_root_get(bp) != 0) { + if (bzb_usr_get(bp) != 0) { + s = "RUFS"; + } else { + s = "RFS"; + } + j = 0; + } else if (bzb_usr_get(bp) != 0) { + s = "UFS"; + j = 2; + } else { + s = "FS"; + } + break; + } + if (bzb_slice_get(bp) != 0) { + printf(" s%1d %4s", bzb_slice_get(bp)-1, s); + } else if (j >= 0) { + printf(" S%1d %4s", j, s); + } else { + printf(" %4s", s); + } + if (bzb_crit_get(bp) != 0) { + printf(" K%1d", bp->bzb_cluster); + } else if (j < 0) { + printf(" "); + } else { + printf(" k%1d", bp->bzb_cluster); + } + if (bp->bzb_mount_point[0] != 0) { + printf(" %.64s", bp->bzb_mount_point); + } + } +#endif + printf("\n"); +} + + +void +list_all_disks() +{ + MEDIA_ITERATOR iter; + MEDIA m; + DPME * data; + char *name; + long mark; + + data = (DPME *) malloc(PBLOCK_SIZE); + if (data == NULL) { + error(errno, "can't allocate memory for try buffer"); + return; + } + + for (iter = first_media_kind(&mark); iter != 0; iter = next_media_kind(&mark)) { + + while ((name = step_media_iterator(iter)) != 0) { + + if ((m = open_pathname_as_media(name, O_RDONLY)) == 0) { + error(errno, "can't open file '%s'", name); + } else { + close_media(m); + + dump(name); + } + free(name); + } + + delete_media_iterator(iter); + } + + free(data); +} + + +void +show_data_structures(partition_map_header *map) +{ + Block0 *zp; + DDMap *m; + int i; + int j; + partition_map * entry; + DPME *p; + BZB *bp; + char *s; + + if (map == NULL) { + printf("No partition map exists\n"); + return; + } + printf("Header:\n"); + printf("map %d blocks out of %d, media %lu blocks (%d byte blocks)\n", + map->blocks_in_map, map->maximum_in_map, + map->media_size, map->logical_block); + printf("Map is%s writeable", (map->writeable)?kStringEmpty:kStringNot); + printf(", but%s changed\n", (map->changed)?kStringEmpty:kStringNot); + printf("\n"); + + if (map->misc == NULL) { + printf("No block zero\n"); + } else { + zp = map->misc; + + printf("Block0:\n"); + printf("signature 0x%x", zp->sbSig); + if (zp->sbSig == BLOCK0_SIGNATURE) { + printf("\n"); + } else { + printf(" should be 0x%x\n", BLOCK0_SIGNATURE); + } + printf("Block size=%u, Number of Blocks=%lu\n", + zp->sbBlkSize, zp->sbBlkCount); + printf("DeviceType=0x%x, DeviceId=0x%x, sbData=0x%lx\n", + zp->sbDevType, zp->sbDevId, zp->sbData); + if (zp->sbDrvrCount == 0) { + printf("No drivers\n"); + } else { + printf("%u driver%s-\n", zp->sbDrvrCount, + (zp->sbDrvrCount>1)?"s":kStringEmpty); + m = (DDMap *) zp->sbMap; + for (i = 0; i < zp->sbDrvrCount; i++) { + printf("%u: @ %lu for %u, type=0x%x\n", i+1, + get_align_long(&m[i].ddBlock), + m[i].ddSize, m[i].ddType); + } + } + } + printf("\n"); + +/* +u32 dpme_boot_args[32] ; +u32 dpme_reserved_3[62] ; +*/ + printf(" #: type length base " + "flags (logical)\n"); + for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { + p = entry->data; + printf("%2ld: %20.32s ", + entry->disk_address, p->dpme_type); + printf("%7lu @ %-7lu ", p->dpme_pblocks, p->dpme_pblock_start); + printf("%c%c%c%c%c%c%c%c%c%c%c%c ", + (dpme_valid_get(p))?'V':'.', + (dpme_allocated_get(p))?'A':'.', + (dpme_in_use_get(p))?'I':'.', + (dpme_bootable_get(p))?'B':'.', + (dpme_readable_get(p))?'R':'.', + (dpme_writable_get(p))?'W':'.', + (dpme_os_pic_code_get(p))?'P':'.', + (dpme_os_specific_2_get(p))?'2':'.', + (dpme_chainable_get(p))?'C':'.', + (dpme_diskdriver_get(p))?'D':'.', + (bitfield_get(p->dpme_flags, 30, 1))?'M':'.', + (bitfield_get(p->dpme_flags, 31, 1))?'X':'.'); + if (p->dpme_lblock_start != 0 || p->dpme_pblocks != p->dpme_lblocks) { + printf("(%lu @ %lu)", p->dpme_lblocks, p->dpme_lblock_start); + } + printf("\n"); + } + printf("\n"); + printf(" #: booter bytes load_address " + "goto_address checksum processor\n"); + for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { + p = entry->data; + printf("%2ld: ", entry->disk_address); + printf("%7lu ", p->dpme_boot_block); + printf("%7lu ", p->dpme_boot_bytes); + printf("%8lx ", (u32)p->dpme_load_addr); + printf("%8lx ", (u32)p->dpme_load_addr_2); + printf("%8lx ", (u32)p->dpme_goto_addr); + printf("%8lx ", (u32)p->dpme_goto_addr_2); + printf("%8lx ", p->dpme_checksum); + printf("%.32s", p->dpme_process_id); + printf("\n"); + } + printf("\n"); +/* +xx: cccc RU *dd s... +*/ + printf(" #: type RU *slice mount_point (A/UX only fields)\n"); + for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { + p = entry->data; + printf("%2ld: ", entry->disk_address); + + bp = (BZB *) (p->dpme_bzb); + j = -1; + if (bp->bzb_magic == BZBMAGIC) { + switch (bp->bzb_type) { + case FSTEFS: + s = "esch"; + break; + case FSTSFS: + s = "swap"; + j = 1; + break; + case FST: + default: + s = "fsys"; + if (bzb_root_get(bp) != 0) { + j = 0; + } else if (bzb_usr_get(bp) != 0) { + j = 2; + } + break; + } + printf("%4s ", s); + printf("%c%c ", + (bzb_root_get(bp))?'R':' ', + (bzb_usr_get(bp))?'U':' '); + if (bzb_slice_get(bp) != 0) { + printf(" %2ld", bzb_slice_get(bp)-1); + } else if (j >= 0) { + printf(" *%2d", j); + } else { + printf(" "); + } + if (bp->bzb_mount_point[0] != 0) { + printf(" %.64s", bp->bzb_mount_point); + } + } + printf("\n"); + } +} + + +void +full_dump_partition_entry(partition_map_header *map, int index) +{ + partition_map * cur; + DPME *p; + int i; + u32 t; + + cur = find_entry_by_disk_address(index, map); + if (cur == NULL) { + printf("No such partition\n"); + return; + } + + p = cur->data; + printf(" signature: 0x%x\n", p->dpme_signature); + printf(" reserved1: 0x%x\n", p->dpme_reserved_1); + printf(" number of map entries: %ld\n", p->dpme_map_entries); + printf(" physical start: %10lu length: %10lu\n", p->dpme_pblock_start, p->dpme_pblocks); + printf(" logical start: %10lu length: %10lu\n", p->dpme_lblock_start, p->dpme_lblocks); + + printf(" flags: 0x%lx\n", (u32)p->dpme_flags); + printf(" "); + if (dpme_valid_get(p)) printf("valid "); + if (dpme_allocated_get(p)) printf("alloc "); + if (dpme_in_use_get(p)) printf("in-use "); + if (dpme_bootable_get(p)) printf("boot "); + if (dpme_readable_get(p)) printf("read "); + if (dpme_writable_get(p)) printf("write "); + if (dpme_os_pic_code_get(p)) printf("pic "); + t = p->dpme_flags >> 7; + for (i = 7; i <= 31; i++) { + if (t & 0x1) { + printf("%d ", i); + } + t = t >> 1; + } + printf("\n"); + + printf(" name: '%.32s'\n", p->dpme_name); + printf(" type: '%.32s'\n", p->dpme_type); + + printf(" boot start block: %10lu\n", p->dpme_boot_block); + printf("boot length (in bytes): %10lu\n", p->dpme_boot_bytes); + printf(" load address: 0x%08lx 0x%08lx\n", + (u32)p->dpme_load_addr, (u32)p->dpme_load_addr_2); + printf(" start address: 0x%08lx 0x%08lx\n", + (u32)p->dpme_goto_addr, (u32)p->dpme_goto_addr_2); + printf(" checksum: 0x%08lx\n", p->dpme_checksum); + printf(" processor: '%.32s'\n", p->dpme_process_id); + printf("boot args field -"); + dump_block((unsigned char *)p->dpme_boot_args, 32*4); + printf("dpme_reserved_3 -"); + dump_block((unsigned char *)p->dpme_reserved_3, 62*4); +} + + +void +dump_block(unsigned char *addr, int len) +{ + int i; + int j; + int limit1; + int limit; +#define LINE_LEN 16 +#define UNIT_LEN 4 +#define OTHER_LEN 8 + + for (i = 0; i < len; i = limit) { + limit1 = i + LINE_LEN; + if (limit1 > len) { + limit = len; + } else { + limit = limit1; + } + printf("\n%03x: ", i); + for (j = i; j < limit1; j++) { + if (j % UNIT_LEN == 0) { + printf(" "); + } + if (j < limit) { + printf("%02x", addr[j]); + } else { + printf(" "); + } + } + printf(" "); + for (j = i; j < limit; j++) { + if (j % OTHER_LEN == 0) { + printf(" "); + } + if (addr[j] < ' ') { + printf("."); + } else { + printf("%c", addr[j]); + } + } + } + printf("\n"); +} + +void +full_dump_block_zero(partition_map_header *map) +{ + Block0 *zp; + DDMap *m; + int i; + + if (map == NULL) { + printf("No partition map exists\n"); + return; + } + + if (map->misc == NULL) { + printf("No block zero\n"); + return; + } + zp = map->misc; + + printf(" signature: 0x%x\n", zp->sbSig); + printf(" size of a block: %d\n", zp->sbBlkSize); + printf(" number of blocks: %ld\n", zp->sbBlkCount); + printf(" device type: 0x%x\n", zp->sbDevType); + printf(" device id: 0x%x\n", zp->sbDevId); + printf(" data: 0x%lx\n", zp->sbData); + printf(" driver count: %d\n", zp->sbDrvrCount); + m = (DDMap *) zp->sbMap; + for (i = 0; &m[i].ddType < &zp->sbMap[247]; i++) { + if (m[i].ddBlock == 0 && m[i].ddSize == 0 && m[i].ddType == 0) { + break; + } + printf(" driver %3u block: %ld\n", i+1, m[i].ddBlock); + printf(" size in blocks: %d\n", m[i].ddSize); + printf(" driver type: 0x%x\n", m[i].ddType); + } + printf("remainder of block -"); + dump_block((unsigned char *)&m[i].ddBlock, (&zp->sbMap[247]-((unsigned short *)&m[i].ddBlock))*2); +} + +void +display_patches(partition_map *entry) +{ + long long offset; + MEDIA m; + static unsigned char *patch_block; + + offset = entry->data->dpme_pblock_start; + m = entry->the_map->m; + offset = ((long long) entry->data->dpme_pblock_start) * entry->the_map->logical_block; + if (patch_block == NULL) { + patch_block = (unsigned char *) malloc(PBLOCK_SIZE); + if (patch_block == NULL) { + error(errno, "can't allocate memory for patch block buffer"); + return; + } + } + if (read_media(m, (long long)offset, PBLOCK_SIZE, (char *)patch_block) == 0) { + error(errno, "Can't read patch block"); + return; + } + dump_block(patch_block, PBLOCK_SIZE); +} + +int +strnlen(char *s, int n) +{ + int i; + + for (i = 0; i < n; i++) { + if (*s == 0) { + break; + } + s++; + } + return i; +} + +int +get_max_type_string_length(partition_map_header *map) +{ + partition_map * entry; + int max; + int length; + + if (map == NULL) { + return 0; + } + + max = 0; + + for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { + length = strnlen(entry->data->dpme_type, DPISTRLEN); + if (length > max) { + max = length; + } + } + + return max; +} + +int +get_max_name_string_length(partition_map_header *map) +{ + partition_map * entry; + int max; + int length; + + if (map == NULL) { + return 0; + } + + max = 0; + + for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { + length = strnlen(entry->data->dpme_name, DPISTRLEN); + if (length > max) { + max = length; + } + } + + return max; +} + +int +get_max_base_or_length(partition_map_header *map) +{ + partition_map * entry; + int max; + + if (map == NULL) { + return 0; + } + + max = 0; + + for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { + if (entry->data->dpme_pblock_start > max) { + max = entry->data->dpme_pblock_start; + } + if (entry->data->dpme_pblocks > max) { + max = entry->data->dpme_pblocks; + } + if (entry->data->dpme_lblock_start > max) { + max = entry->data->dpme_lblock_start; + } + if (entry->data->dpme_lblocks > max) { + max = entry->data->dpme_lblocks; + } + } + + return max; +} + +void +adjust_value_and_compute_prefix(double *value, int *prefix) +{ + double bytes; + int multiplier; + + bytes = *value; + if (bytes < 1024.0) { + multiplier = ' '; + } else { + bytes = bytes / 1024.0; + if (bytes < 1024.0) { + multiplier = 'K'; + } else { + bytes = bytes / 1024.0; + if (bytes < 1024.0) { + multiplier = 'M'; + } else { + bytes = bytes / 1024.0; + if (bytes < 1024.0) { + multiplier = 'G'; + } else { + bytes = bytes / 1024.0; + multiplier = 'T'; + } + } + } + } + *value = bytes; + *prefix = multiplier; +} |