xref: /netbsd-src/external/bsd/pdisk/dist/dump.c (revision 48a628ae0434c4247b560ad8f2eb1dc06d0dd070)
19428323dSchristos //
29428323dSchristos // dump.c - dumping partition maps
39428323dSchristos //
49428323dSchristos // Written by Eryk Vershen
59428323dSchristos //
69428323dSchristos 
79428323dSchristos /*
89428323dSchristos  * Copyright 1996,1997,1998 by Apple Computer, Inc.
99428323dSchristos  *              All Rights Reserved
109428323dSchristos  *
119428323dSchristos  * Permission to use, copy, modify, and distribute this software and
129428323dSchristos  * its documentation for any purpose and without fee is hereby granted,
139428323dSchristos  * provided that the above copyright notice appears in all copies and
149428323dSchristos  * that both the copyright notice and this permission notice appear in
159428323dSchristos  * supporting documentation.
169428323dSchristos  *
179428323dSchristos  * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
189428323dSchristos  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
199428323dSchristos  * FOR A PARTICULAR PURPOSE.
209428323dSchristos  *
219428323dSchristos  * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
229428323dSchristos  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
239428323dSchristos  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
249428323dSchristos  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
259428323dSchristos  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
269428323dSchristos  */
279428323dSchristos 
289428323dSchristos // for *printf()
299428323dSchristos #include <stdio.h>
309428323dSchristos 
319428323dSchristos // for malloc() & free()
329428323dSchristos #ifndef __linux__
339428323dSchristos #include <stdlib.h>
349428323dSchristos //#include <unistd.h>
359428323dSchristos #else
369428323dSchristos #include <malloc.h>
379428323dSchristos #endif
389428323dSchristos 
399428323dSchristos // for strcmp()
409428323dSchristos #include <string.h>
419428323dSchristos // for O_RDONLY
429428323dSchristos #include <fcntl.h>
439428323dSchristos // for errno
449428323dSchristos #include <errno.h>
45*48a628aeSchristos #include <inttypes.h>
469428323dSchristos 
479428323dSchristos #include "dump.h"
489428323dSchristos #include "pathname.h"
499428323dSchristos #include "io.h"
509428323dSchristos #include "errors.h"
519428323dSchristos 
529428323dSchristos 
539428323dSchristos //
549428323dSchristos // Defines
559428323dSchristos //
569428323dSchristos #if DPISTRLEN != 32
579428323dSchristos #error Change in strlen in partition entries! Fix constants
589428323dSchristos #endif
599428323dSchristos 
609428323dSchristos #define get_align_long(x)	(*(x))
619428323dSchristos 
629428323dSchristos 
639428323dSchristos //
649428323dSchristos // Types
659428323dSchristos //
669428323dSchristos typedef struct names {
67*48a628aeSchristos     const char *abbr;
68*48a628aeSchristos     const char *full;
699428323dSchristos } NAMES;
709428323dSchristos 
719428323dSchristos #ifdef __unix__
72*48a628aeSchristos typedef uint32_t OSType;
739428323dSchristos #endif
749428323dSchristos 
759428323dSchristos typedef struct PatchDescriptor {
769428323dSchristos     OSType	patchSig;
77*48a628aeSchristos     uint16_t	majorVers;
78*48a628aeSchristos     uint16_t	minorVers;
79*48a628aeSchristos     uint32_t	flags;
80*48a628aeSchristos     uint32_t	patchOffset;
81*48a628aeSchristos     uint32_t	patchSize;
82*48a628aeSchristos     uint32_t	patchCRC;
83*48a628aeSchristos     uint32_t	patchDescriptorLen;
84*48a628aeSchristos     uint8_t	patchName[33];
85*48a628aeSchristos     uint8_t	patchVendor[1];
869428323dSchristos } PatchDescriptor;
879428323dSchristos typedef PatchDescriptor * PatchDescriptorPtr;
889428323dSchristos 
899428323dSchristos typedef struct PatchList {
90*48a628aeSchristos     uint16_t numPatchBlocks;	// number of disk blocks to hold the patch list
91*48a628aeSchristos     uint16_t numPatches;		// number of patches in list
929428323dSchristos     PatchDescriptor thePatch[1];
939428323dSchristos } PatchList;
949428323dSchristos typedef PatchList *PatchListPtr;
959428323dSchristos 
969428323dSchristos 
979428323dSchristos //
989428323dSchristos // Global Constants
999428323dSchristos //
1009428323dSchristos NAMES plist[] = {
1019428323dSchristos     {"Drvr", "Apple_Driver"},
1029428323dSchristos     {"Drv4", "Apple_Driver43"},
1039428323dSchristos     {"Free", "Apple_Free"},
1049428323dSchristos     {"Patc", "Apple_Patches"},
1059428323dSchristos     {" HFS", "Apple_HFS"},
1069428323dSchristos     {" MFS", "Apple_MFS"},
1079428323dSchristos     {"PDOS", "Apple_PRODOS"},
1089428323dSchristos     {"junk", "Apple_Scratch"},
1099428323dSchristos     {"unix", "Apple_UNIX_SVR2"},
1109428323dSchristos     {" map", "Apple_partition_map"},
1119428323dSchristos     {0,	0},
1129428323dSchristos };
1139428323dSchristos 
1149428323dSchristos const char * kStringEmpty	= "";
1159428323dSchristos const char * kStringNot		= " not";
1169428323dSchristos 
1179428323dSchristos 
1189428323dSchristos //
1199428323dSchristos // Global Variables
1209428323dSchristos //
1219428323dSchristos int aflag = AFLAG_DEFAULT;	/* abbreviate partition types */
1229428323dSchristos int pflag = PFLAG_DEFAULT;	/* show physical limits of partition */
1239428323dSchristos int fflag = FFLAG_DEFAULT;	/* show HFS volume names */
1249428323dSchristos 
1259428323dSchristos 
1269428323dSchristos //
1279428323dSchristos // Forward declarations
1289428323dSchristos //
1299428323dSchristos void adjust_value_and_compute_prefix(double *value, int *prefix);
1309428323dSchristos void dump_block_zero(partition_map_header *map);
1319428323dSchristos void dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits);
1329428323dSchristos int get_max_base_or_length(partition_map_header *map);
1339428323dSchristos int get_max_name_string_length(partition_map_header *map);
1349428323dSchristos int get_max_type_string_length(partition_map_header *map);
1359428323dSchristos 
1369428323dSchristos 
1379428323dSchristos //
1389428323dSchristos // Routines
1399428323dSchristos //
1409428323dSchristos int
dump(char * name)1419428323dSchristos dump(char *name)
1429428323dSchristos {
1439428323dSchristos     partition_map_header *map;
1449428323dSchristos     int junk;
1459428323dSchristos 
1469428323dSchristos     map = open_partition_map(name, &junk, 0);
1479428323dSchristos     if (map == NULL) {
1489428323dSchristos 	//error(-1, "No partition map in '%s'", name);
1499428323dSchristos 	return 0;
1509428323dSchristos     }
1519428323dSchristos 
1529428323dSchristos     dump_partition_map(map, 1);
1539428323dSchristos 
1549428323dSchristos     close_partition_map(map);
1559428323dSchristos 
1569428323dSchristos     return 1;
1579428323dSchristos }
1589428323dSchristos 
1599428323dSchristos 
1609428323dSchristos void
dump_block_zero(partition_map_header * map)1619428323dSchristos dump_block_zero(partition_map_header *map)
1629428323dSchristos {
1639428323dSchristos     Block0 *p;
1649428323dSchristos     DDMap *m;
1659428323dSchristos     int i;
1669428323dSchristos     double value;
1679428323dSchristos     int prefix;
168*48a628aeSchristos     int32_t t;
1699428323dSchristos 
1709428323dSchristos     p = map->misc;
1719428323dSchristos     if (p->sbSig != BLOCK0_SIGNATURE) {
1729428323dSchristos 	return;
1739428323dSchristos     }
1749428323dSchristos 
1759428323dSchristos     value = ((double)p->sbBlkCount) * p->sbBlkSize;
1769428323dSchristos     adjust_value_and_compute_prefix(&value, &prefix);
177*48a628aeSchristos     printf("\nDevice block size=%u, Number of Blocks=%"PRIu32" (%1.1f%c)\n",
1789428323dSchristos 	    p->sbBlkSize, p->sbBlkCount, value, prefix);
1799428323dSchristos 
1809428323dSchristos     printf("DeviceType=0x%x, DeviceId=0x%x\n",
1819428323dSchristos 	    p->sbDevType, p->sbDevId);
1829428323dSchristos     if (p->sbDrvrCount > 0) {
1839428323dSchristos 	printf("Drivers-\n");
1849428323dSchristos 	m = (DDMap *) p->sbMap;
1859428323dSchristos 	for (i = 0; i < p->sbDrvrCount; i++) {
186*48a628aeSchristos 	    printf("%u: %3u @ %"PRIu32", ", i+1,
1879428323dSchristos 		    m[i].ddSize, get_align_long(&m[i].ddBlock));
1889428323dSchristos 	    if (map->logical_block != p->sbBlkSize) {
1899428323dSchristos 		t = (m[i].ddSize * p->sbBlkSize) / map->logical_block;
190*48a628aeSchristos 		printf("(%"PRIu32"@", t);
1919428323dSchristos 		t = (get_align_long(&m[i].ddBlock) * p->sbBlkSize)
1929428323dSchristos 			/ map->logical_block;
193*48a628aeSchristos 		printf("%"PRIu32")  ", t);
1949428323dSchristos 	    }
1959428323dSchristos 	    printf("type=0x%x\n", m[i].ddType);
1969428323dSchristos 	}
1979428323dSchristos     }
1989428323dSchristos     printf("\n");
1999428323dSchristos }
2009428323dSchristos 
2019428323dSchristos 
2029428323dSchristos void
dump_partition_map(partition_map_header * map,int disk_order)2039428323dSchristos dump_partition_map(partition_map_header *map, int disk_order)
2049428323dSchristos {
2059428323dSchristos     partition_map * entry;
2069428323dSchristos     int max_type_length;
2079428323dSchristos     int max_name_length;
2089428323dSchristos     int digits;
2099428323dSchristos     char *alternate;
2109428323dSchristos 
2119428323dSchristos     if (map == NULL) {
2129428323dSchristos 	bad_input("No partition map exists");
2139428323dSchristos 	return;
2149428323dSchristos     }
2159428323dSchristos     alternate = get_linux_name(map->name);
2169428323dSchristos     if (alternate) {
2179428323dSchristos 	printf("\nPartition map (with %d byte blocks) on '%s' (%s)\n",
2189428323dSchristos 		map->logical_block, map->name, alternate);
2199428323dSchristos 	free(alternate);
2209428323dSchristos     } else {
2219428323dSchristos 	printf("\nPartition map (with %d byte blocks) on '%s'\n",
2229428323dSchristos 		map->logical_block, map->name);
2239428323dSchristos     }
2249428323dSchristos 
2259428323dSchristos     digits = number_of_digits(get_max_base_or_length(map));
2269428323dSchristos     if (digits < 6) {
2279428323dSchristos 	digits = 6;
2289428323dSchristos     }
2299428323dSchristos     if (aflag) {
2309428323dSchristos 	max_type_length = 4;
2319428323dSchristos     } else {
2329428323dSchristos 	max_type_length = get_max_type_string_length(map);
2339428323dSchristos 	if (max_type_length < 4) {
2349428323dSchristos 	    max_type_length = 4;
2359428323dSchristos 	}
2369428323dSchristos     }
2379428323dSchristos     max_name_length = get_max_name_string_length(map);
2389428323dSchristos     if (max_name_length < 6) {
2399428323dSchristos 	max_name_length = 6;
2409428323dSchristos     }
2419428323dSchristos     printf(" #: %*s %-*s %*s   %-*s ( size )\n",
2429428323dSchristos 	    max_type_length, "type",
2439428323dSchristos 	    max_name_length, "name",
2449428323dSchristos 	    digits, "length", digits, "base");
2459428323dSchristos 
2469428323dSchristos     if (disk_order) {
2479428323dSchristos 	for (entry = map->disk_order; entry != NULL;
2489428323dSchristos 		entry = entry->next_on_disk) {
2499428323dSchristos 
2509428323dSchristos 	    dump_partition_entry(entry, max_type_length, max_name_length, digits);
2519428323dSchristos 	}
2529428323dSchristos     } else {
2539428323dSchristos 	for (entry = map->base_order; entry != NULL;
2549428323dSchristos 		entry = entry->next_by_base) {
2559428323dSchristos 
2569428323dSchristos 	    dump_partition_entry(entry, max_type_length, max_name_length, digits);
2579428323dSchristos 	}
2589428323dSchristos     }
2599428323dSchristos     dump_block_zero(map);
2609428323dSchristos }
2619428323dSchristos 
2629428323dSchristos 
2639428323dSchristos void
dump_partition_entry(partition_map * entry,int type_length,int name_length,int digits)2649428323dSchristos dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits)
2659428323dSchristos {
2669428323dSchristos     partition_map_header *map;
2679428323dSchristos     int j;
2689428323dSchristos     DPME *p;
269*48a628aeSchristos     const char *s;
270*48a628aeSchristos     uint32_t size;
2719428323dSchristos     double bytes;
2729428323dSchristos     int driver;
2739428323dSchristos     // int kind;
2749428323dSchristos     char *buf;
275*48a628aeSchristos #if 1
276*48a628aeSchristos     BZB *bp;
277*48a628aeSchristos #endif
2789428323dSchristos 
2799428323dSchristos     map = entry->the_map;
2809428323dSchristos     p = entry->data;
2819428323dSchristos     driver = entry->contains_driver? '*': ' ';
2829428323dSchristos     if (aflag) {
2839428323dSchristos 	s = "????";
2849428323dSchristos 	for (j = 0; plist[j].abbr != 0; j++) {
2859428323dSchristos 	    if (strcmp(p->dpme_type, plist[j].full) == 0) {
2869428323dSchristos 		s = plist[j].abbr;
2879428323dSchristos 		break;
2889428323dSchristos 	    }
2899428323dSchristos 	}
290*48a628aeSchristos 	printf("%2"PRIu32": %.4s", entry->disk_address, s);
2919428323dSchristos     } else {
292*48a628aeSchristos 	printf("%2"PRIu32": %*.32s", entry->disk_address, type_length, p->dpme_type);
2939428323dSchristos     }
2949428323dSchristos 
2959428323dSchristos     buf = (char *) malloc(name_length+1);
2969428323dSchristos     if (entry->HFS_name == NULL || fflag == 0) {
2979428323dSchristos 	strncpy(buf, p->dpme_name, name_length);
2989428323dSchristos 	buf[name_length] = 0;
2999428323dSchristos     } else {
300*48a628aeSchristos 	snprintf(buf, name_length + 1, "\"%s\"", entry->HFS_name);
3019428323dSchristos     }
3029428323dSchristos     printf("%c%-*.32s ", driver, name_length, buf);
3039428323dSchristos     free(buf);
3049428323dSchristos     /*
3059428323dSchristos     switch (entry->HFS_kind) {
3069428323dSchristos     case kHFS_std:	kind = 'h'; break;
3079428323dSchristos     case kHFS_embed:	kind = 'e'; break;
3089428323dSchristos     case kHFS_plus:	kind = '+'; break;
3099428323dSchristos     default:
3109428323dSchristos     case kHFS_not:	kind = ' '; break;
3119428323dSchristos     }
3129428323dSchristos     printf("%c ", kind);
3139428323dSchristos     */
3149428323dSchristos 
3159428323dSchristos     if (pflag) {
316*48a628aeSchristos 	printf("%*"PRIu32" ", digits, p->dpme_pblocks);
3179428323dSchristos 	size = p->dpme_pblocks;
3189428323dSchristos     } else if (p->dpme_lblocks + p->dpme_lblock_start != p->dpme_pblocks) {
319*48a628aeSchristos 	printf("%*"PRIu32"+", digits, p->dpme_lblocks);
3209428323dSchristos 	size = p->dpme_lblocks;
3219428323dSchristos     } else if (p->dpme_lblock_start != 0) {
322*48a628aeSchristos 	printf("%*"PRIu32" ", digits, p->dpme_lblocks);
3239428323dSchristos 	size = p->dpme_lblocks;
3249428323dSchristos     } else {
325*48a628aeSchristos 	printf("%*"PRIu32" ", digits, p->dpme_pblocks);
3269428323dSchristos 	size = p->dpme_pblocks;
3279428323dSchristos     }
3289428323dSchristos     if (pflag || p->dpme_lblock_start == 0) {
329*48a628aeSchristos 	printf("@ %-*"PRIu32"", digits, p->dpme_pblock_start);
3309428323dSchristos     } else {
331*48a628aeSchristos 	printf("@~%-*"PRIu32"", digits, p->dpme_pblock_start + p->dpme_lblock_start);
3329428323dSchristos     }
3339428323dSchristos 
3349428323dSchristos     bytes = ((double)size) * map->logical_block;
3359428323dSchristos     adjust_value_and_compute_prefix(&bytes, &j);
3369428323dSchristos     if (j != ' ' && j != 'K') {
3379428323dSchristos 	printf(" (%#5.1f%c)", bytes, j);
3389428323dSchristos     }
3399428323dSchristos 
340*48a628aeSchristos #if 1
3419428323dSchristos     // Old A/UX fields that no one pays attention to anymore.
3429428323dSchristos     bp = (BZB *) (p->dpme_bzb);
3439428323dSchristos     j = -1;
3449428323dSchristos     if (bp->bzb_magic == BZBMAGIC) {
3459428323dSchristos 	switch (bp->bzb_type) {
3469428323dSchristos 	case FSTEFS:
3479428323dSchristos 	    s = "EFS";
3489428323dSchristos 	    break;
3499428323dSchristos 	case FSTSFS:
3509428323dSchristos 	    s = "SFS";
3519428323dSchristos 	    j = 1;
3529428323dSchristos 	    break;
3539428323dSchristos 	case FST:
3549428323dSchristos 	default:
3559428323dSchristos 	    if (bzb_root_get(bp) != 0) {
3569428323dSchristos 		if (bzb_usr_get(bp) != 0) {
3579428323dSchristos 		    s = "RUFS";
3589428323dSchristos 		} else {
3599428323dSchristos 		    s = "RFS";
3609428323dSchristos 		}
3619428323dSchristos 		j = 0;
3629428323dSchristos 	    } else if (bzb_usr_get(bp) != 0) {
3639428323dSchristos 		s = "UFS";
3649428323dSchristos 		j = 2;
3659428323dSchristos 	    } else {
3669428323dSchristos 		s = "FS";
3679428323dSchristos 	    }
3689428323dSchristos 	    break;
3699428323dSchristos 	}
3709428323dSchristos 	if (bzb_slice_get(bp) != 0) {
371*48a628aeSchristos 	    printf(" s%1"PRId32" %4s", bzb_slice_get(bp)-1, s);
3729428323dSchristos 	} else if (j >= 0) {
3739428323dSchristos 	    printf(" S%1d %4s", j, s);
3749428323dSchristos 	} else {
3759428323dSchristos 	    printf("    %4s", s);
3769428323dSchristos 	}
3779428323dSchristos 	if (bzb_crit_get(bp) != 0) {
3789428323dSchristos 	    printf(" K%1d", bp->bzb_cluster);
3799428323dSchristos 	} else if (j < 0) {
3809428323dSchristos 	    printf("   ");
3819428323dSchristos 	} else {
3829428323dSchristos 	    printf(" k%1d", bp->bzb_cluster);
3839428323dSchristos 	}
3849428323dSchristos 	if (bp->bzb_mount_point[0] != 0) {
3859428323dSchristos 	    printf("  %.64s", bp->bzb_mount_point);
3869428323dSchristos 	}
3879428323dSchristos     }
3889428323dSchristos #endif
3899428323dSchristos     printf("\n");
3909428323dSchristos }
3919428323dSchristos 
3929428323dSchristos 
3939428323dSchristos void
list_all_disks(void)394*48a628aeSchristos list_all_disks(void)
3959428323dSchristos {
3969428323dSchristos     MEDIA_ITERATOR iter;
3979428323dSchristos     MEDIA m;
3989428323dSchristos     DPME * data;
3999428323dSchristos     char *name;
4009428323dSchristos     long mark;
4019428323dSchristos 
4029428323dSchristos     data = (DPME *) malloc(PBLOCK_SIZE);
4039428323dSchristos     if (data == NULL) {
4049428323dSchristos 	error(errno, "can't allocate memory for try buffer");
4059428323dSchristos 	return;
4069428323dSchristos     }
4079428323dSchristos 
4089428323dSchristos     for (iter = first_media_kind(&mark); iter != 0; iter = next_media_kind(&mark)) {
4099428323dSchristos 
4109428323dSchristos     	while ((name = step_media_iterator(iter)) != 0) {
4119428323dSchristos 
4129428323dSchristos 	    if ((m = open_pathname_as_media(name, O_RDONLY)) == 0) {
4139428323dSchristos #if defined(__linux__) || defined(__unix__)
4149428323dSchristos 		error(errno, "can't open file '%s'", name);
4159428323dSchristos #endif
4169428323dSchristos 	    } else {
4179428323dSchristos 		close_media(m);
4189428323dSchristos 
4199428323dSchristos 		dump(name);
4209428323dSchristos 	    }
4219428323dSchristos 	    free(name);
4229428323dSchristos 	}
4239428323dSchristos 
4249428323dSchristos 	delete_media_iterator(iter);
4259428323dSchristos     }
4269428323dSchristos 
4279428323dSchristos     free(data);
4289428323dSchristos }
4299428323dSchristos 
4309428323dSchristos 
4319428323dSchristos void
show_data_structures(partition_map_header * map)4329428323dSchristos show_data_structures(partition_map_header *map)
4339428323dSchristos {
4349428323dSchristos     Block0 *zp;
4359428323dSchristos     DDMap *m;
4369428323dSchristos     int i;
4379428323dSchristos     int j;
4389428323dSchristos     partition_map * entry;
4399428323dSchristos     DPME *p;
4409428323dSchristos     BZB *bp;
441*48a628aeSchristos     const char *s;
4429428323dSchristos 
4439428323dSchristos     if (map == NULL) {
4449428323dSchristos 	printf("No partition map exists\n");
4459428323dSchristos 	return;
4469428323dSchristos     }
4479428323dSchristos     printf("Header:\n");
448*48a628aeSchristos     printf("map %d blocks out of %d,  media %"PRIu32" blocks (%d byte blocks)\n",
4499428323dSchristos 	    map->blocks_in_map, map->maximum_in_map,
4509428323dSchristos 	    map->media_size, map->logical_block);
451*48a628aeSchristos     printf("Map is%s writable", (map->writable)?kStringEmpty:kStringNot);
4529428323dSchristos     printf(", but%s changed", (map->changed)?kStringEmpty:kStringNot);
4539428323dSchristos     printf(" and has%s been written\n", (map->written)?kStringEmpty:kStringNot);
4549428323dSchristos     printf("\n");
4559428323dSchristos 
4569428323dSchristos     if (map->misc == NULL) {
4579428323dSchristos 	printf("No block zero\n");
4589428323dSchristos     } else {
4599428323dSchristos 	zp = map->misc;
4609428323dSchristos 
4619428323dSchristos 	printf("Block0:\n");
4629428323dSchristos 	printf("signature 0x%x", zp->sbSig);
4639428323dSchristos 	if (zp->sbSig == BLOCK0_SIGNATURE) {
4649428323dSchristos 	    printf("\n");
4659428323dSchristos 	} else {
4669428323dSchristos 	    printf(" should be 0x%x\n", BLOCK0_SIGNATURE);
4679428323dSchristos 	}
468*48a628aeSchristos 	printf("Block size=%u, Number of Blocks=%"PRIu32"\n",
4699428323dSchristos 		zp->sbBlkSize, zp->sbBlkCount);
470*48a628aeSchristos 	printf("DeviceType=0x%x, DeviceId=0x%x, sbData=0x%"PRIx32"\n",
4719428323dSchristos 		zp->sbDevType, zp->sbDevId, zp->sbData);
4729428323dSchristos 	if (zp->sbDrvrCount == 0) {
4739428323dSchristos 	    printf("No drivers\n");
4749428323dSchristos 	} else {
4759428323dSchristos 	    printf("%u driver%s-\n", zp->sbDrvrCount,
4769428323dSchristos 		    (zp->sbDrvrCount>1)?"s":kStringEmpty);
4779428323dSchristos 	    m = (DDMap *) zp->sbMap;
4789428323dSchristos 	    for (i = 0; i < zp->sbDrvrCount; i++) {
479*48a628aeSchristos             printf("%u: @ %"PRIu32" for %u, type=0x%x\n", i+1,
4809428323dSchristos 		   get_align_long(&m[i].ddBlock),
4819428323dSchristos 		   m[i].ddSize, m[i].ddType);
4829428323dSchristos 	    }
4839428323dSchristos 	}
4849428323dSchristos     }
4859428323dSchristos     printf("\n");
4869428323dSchristos 
4879428323dSchristos /*
488*48a628aeSchristos uint32_t     dpme_boot_args[32]      ;
489*48a628aeSchristos uint32_t     dpme_reserved_3[62]     ;
4909428323dSchristos */
4919428323dSchristos     printf(" #:                 type  length   base    "
4929428323dSchristos 	    "flags        (logical)\n");
4939428323dSchristos     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
4949428323dSchristos 	p = entry->data;
495*48a628aeSchristos 	printf("%2"PRIu32": %20.32s ",
4969428323dSchristos 		entry->disk_address, p->dpme_type);
497*48a628aeSchristos 	printf("%7"PRIu32" @ %-7"PRIu32" ", p->dpme_pblocks, p->dpme_pblock_start);
4989428323dSchristos 	printf("%c%c%c%c%c%c%c%c%c%c%c%c ",
4999428323dSchristos 		(dpme_valid_get(p))?'V':'.',
5009428323dSchristos 		(dpme_allocated_get(p))?'A':'.',
5019428323dSchristos 		(dpme_in_use_get(p))?'I':'.',
5029428323dSchristos 		(dpme_bootable_get(p))?'B':'.',
5039428323dSchristos 		(dpme_readable_get(p))?'R':'.',
5049428323dSchristos 		(dpme_writable_get(p))?'W':'.',
5059428323dSchristos 		(dpme_os_pic_code_get(p))?'P':'.',
5069428323dSchristos 		(dpme_os_specific_2_get(p))?'2':'.',
5079428323dSchristos 		(dpme_chainable_get(p))?'C':'.',
5089428323dSchristos 		(dpme_diskdriver_get(p))?'D':'.',
5099428323dSchristos 		(bitfield_get(p->dpme_flags, 30, 1))?'M':'.',
5109428323dSchristos 		(bitfield_get(p->dpme_flags, 31, 1))?'X':'.');
5119428323dSchristos 	if (p->dpme_lblock_start != 0 || p->dpme_pblocks != p->dpme_lblocks) {
512*48a628aeSchristos 	    printf("(%"PRIu32" @ %"PRIu32")", p->dpme_lblocks, p->dpme_lblock_start);
5139428323dSchristos 	}
5149428323dSchristos 	printf("\n");
5159428323dSchristos     }
5169428323dSchristos     printf("\n");
5179428323dSchristos     printf(" #:  booter   bytes      load_address      "
5189428323dSchristos 	    "goto_address checksum processor\n");
5199428323dSchristos     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
5209428323dSchristos 	p = entry->data;
521*48a628aeSchristos 	printf("%2"PRIu32": ", entry->disk_address);
522*48a628aeSchristos 	printf("%7"PRIu32" ", p->dpme_boot_block);
523*48a628aeSchristos 	printf("%7"PRIu32" ", p->dpme_boot_bytes);
524*48a628aeSchristos 	printf("%8"PRIx32" ", (uint32_t)p->dpme_load_addr);
525*48a628aeSchristos 	printf("%8"PRIx32" ", (uint32_t)p->dpme_load_addr_2);
526*48a628aeSchristos 	printf("%8"PRIx32" ", (uint32_t)p->dpme_goto_addr);
527*48a628aeSchristos 	printf("%8"PRIx32" ", (uint32_t)p->dpme_goto_addr_2);
528*48a628aeSchristos 	printf("%8"PRIx32" ", p->dpme_checksum);
5299428323dSchristos 	printf("%.32s", p->dpme_process_id);
5309428323dSchristos 	printf("\n");
5319428323dSchristos     }
5329428323dSchristos     printf("\n");
5339428323dSchristos /*
5349428323dSchristos xx: cccc RU *dd s...
5359428323dSchristos */
5369428323dSchristos     printf(" #: type RU *slice mount_point (A/UX only fields)\n");
5379428323dSchristos     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
5389428323dSchristos 	p = entry->data;
539*48a628aeSchristos 	printf("%2"PRIu32": ", entry->disk_address);
5409428323dSchristos 
5419428323dSchristos 	bp = (BZB *) (p->dpme_bzb);
5429428323dSchristos 	j = -1;
5439428323dSchristos 	if (bp->bzb_magic == BZBMAGIC) {
5449428323dSchristos 	    switch (bp->bzb_type) {
5459428323dSchristos 	    case FSTEFS:
5469428323dSchristos 		s = "esch";
5479428323dSchristos 		break;
5489428323dSchristos 	    case FSTSFS:
5499428323dSchristos 		s = "swap";
5509428323dSchristos 		j = 1;
5519428323dSchristos 		break;
5529428323dSchristos 	    case FST:
5539428323dSchristos 	    default:
5549428323dSchristos 		s = "fsys";
5559428323dSchristos 		if (bzb_root_get(bp) != 0) {
5569428323dSchristos 		    j = 0;
5579428323dSchristos 		} else if (bzb_usr_get(bp) != 0) {
5589428323dSchristos 		    j = 2;
5599428323dSchristos 		}
5609428323dSchristos 		break;
5619428323dSchristos 	    }
5629428323dSchristos 	    printf("%4s ", s);
5639428323dSchristos 	    printf("%c%c ",
5649428323dSchristos 		    (bzb_root_get(bp))?'R':' ',
5659428323dSchristos 		    (bzb_usr_get(bp))?'U':' ');
5669428323dSchristos 	    if (bzb_slice_get(bp) != 0) {
567*48a628aeSchristos 		printf("  %2"PRIu32"", bzb_slice_get(bp)-1);
5689428323dSchristos 	    } else if (j >= 0) {
5699428323dSchristos 		printf(" *%2d", j);
5709428323dSchristos 	    } else {
5719428323dSchristos 		printf("    ");
5729428323dSchristos 	    }
5739428323dSchristos 	    if (bp->bzb_mount_point[0] != 0) {
5749428323dSchristos 		printf(" %.64s", bp->bzb_mount_point);
5759428323dSchristos 	    }
5769428323dSchristos 	}
5779428323dSchristos 	printf("\n");
5789428323dSchristos     }
5799428323dSchristos }
5809428323dSchristos 
5819428323dSchristos 
5829428323dSchristos void
full_dump_partition_entry(partition_map_header * map,int ix)583*48a628aeSchristos full_dump_partition_entry(partition_map_header *map, int ix)
5849428323dSchristos {
5859428323dSchristos     partition_map * cur;
5869428323dSchristos     DPME *p;
5879428323dSchristos     int i;
588*48a628aeSchristos     uint32_t t;
5899428323dSchristos 
590*48a628aeSchristos     cur = find_entry_by_disk_address(ix, map);
5919428323dSchristos     if (cur == NULL) {
5929428323dSchristos 	printf("No such partition\n");
5939428323dSchristos 	return;
5949428323dSchristos     }
5959428323dSchristos 
5969428323dSchristos     p = cur->data;
5979428323dSchristos     printf("             signature: 0x%x\n", p->dpme_signature);
5989428323dSchristos     printf("             reserved1: 0x%x\n", p->dpme_reserved_1);
599*48a628aeSchristos     printf(" number of map entries: %"PRId32"\n", p->dpme_map_entries);
600*48a628aeSchristos     printf("        physical start: %10"PRIu32"  length: %10"PRIu32"\n", p->dpme_pblock_start, p->dpme_pblocks);
601*48a628aeSchristos     printf("         logical start: %10"PRIu32"  length: %10"PRIu32"\n", p->dpme_lblock_start, p->dpme_lblocks);
6029428323dSchristos 
603*48a628aeSchristos     printf("                 flags: 0x%"PRIx32"\n", (uint32_t)p->dpme_flags);
6049428323dSchristos     printf("                        ");
6059428323dSchristos     if (dpme_valid_get(p)) printf("valid ");
6069428323dSchristos     if (dpme_allocated_get(p)) printf("alloc ");
6079428323dSchristos     if (dpme_in_use_get(p)) printf("in-use ");
6089428323dSchristos     if (dpme_bootable_get(p)) printf("boot ");
6099428323dSchristos     if (dpme_readable_get(p)) printf("read ");
6109428323dSchristos     if (dpme_writable_get(p)) printf("write ");
6119428323dSchristos     if (dpme_os_pic_code_get(p)) printf("pic ");
6129428323dSchristos     t = p->dpme_flags >> 7;
6139428323dSchristos     for (i = 7; i <= 31; i++) {
6149428323dSchristos     	if (t & 0x1) {
6159428323dSchristos     	    printf("%d ", i);
6169428323dSchristos     	}
6179428323dSchristos     	t = t >> 1;
6189428323dSchristos     }
6199428323dSchristos     printf("\n");
6209428323dSchristos 
6219428323dSchristos     printf("                  name: '%.32s'\n", p->dpme_name);
6229428323dSchristos     printf("                  type: '%.32s'\n", p->dpme_type);
6239428323dSchristos 
624*48a628aeSchristos     printf("      boot start block: %10"PRIu32"\n", p->dpme_boot_block);
625*48a628aeSchristos     printf("boot length (in bytes): %10"PRIu32"\n", p->dpme_boot_bytes);
626*48a628aeSchristos     printf("          load address: 0x%08"PRIx32"  0x%08"PRIx32"\n",
627*48a628aeSchristos 		(uint32_t)p->dpme_load_addr, (uint32_t)p->dpme_load_addr_2);
628*48a628aeSchristos     printf("         start address: 0x%08"PRIx32"  0x%08"PRIx32"\n",
629*48a628aeSchristos 		(uint32_t)p->dpme_goto_addr, (uint32_t)p->dpme_goto_addr_2);
630*48a628aeSchristos     printf("              checksum: 0x%08"PRIx32"\n", p->dpme_checksum);
6319428323dSchristos     printf("             processor: '%.32s'\n", p->dpme_process_id);
6329428323dSchristos     printf("boot args field -");
633*48a628aeSchristos     dump_block((uint8_t *)p->dpme_boot_args, 32*4);
6349428323dSchristos     printf("dpme_reserved_3 -");
635*48a628aeSchristos     dump_block((uint8_t *)p->dpme_reserved_3, 62*4);
6369428323dSchristos }
6379428323dSchristos 
6389428323dSchristos 
6399428323dSchristos void
dump_block(uint8_t * addr,int len)640*48a628aeSchristos dump_block(uint8_t *addr, int len)
6419428323dSchristos {
6429428323dSchristos     int i;
6439428323dSchristos     int j;
6449428323dSchristos     int limit1;
6459428323dSchristos     int limit;
6469428323dSchristos #define LINE_LEN 16
6479428323dSchristos #define UNIT_LEN  4
6489428323dSchristos #define OTHER_LEN  8
6499428323dSchristos 
6509428323dSchristos     for (i = 0; i < len; i = limit) {
6519428323dSchristos     	limit1 = i + LINE_LEN;
6529428323dSchristos     	if (limit1 > len) {
6539428323dSchristos     	    limit = len;
6549428323dSchristos     	} else {
6559428323dSchristos     	    limit = limit1;
6569428323dSchristos     	}
6579428323dSchristos 	printf("\n%03x: ", i);
6589428323dSchristos     	for (j = i; j < limit1; j++) {
6599428323dSchristos 	    if (j % UNIT_LEN == 0) {
6609428323dSchristos 		printf(" ");
6619428323dSchristos 	    }
6629428323dSchristos 	    if (j < limit) {
6639428323dSchristos 		printf("%02x", addr[j]);
6649428323dSchristos 	    } else {
6659428323dSchristos 		printf("  ");
6669428323dSchristos 	    }
6679428323dSchristos     	}
6689428323dSchristos 	printf(" ");
6699428323dSchristos     	for (j = i; j < limit; j++) {
6709428323dSchristos 	    if (j % OTHER_LEN == 0) {
6719428323dSchristos 		printf(" ");
6729428323dSchristos 	    }
6739428323dSchristos     	    if (addr[j] < ' ') {
6749428323dSchristos     	    	printf(".");
6759428323dSchristos     	    } else {
6769428323dSchristos     	    	printf("%c", addr[j]);
6779428323dSchristos     	    }
6789428323dSchristos     	}
6799428323dSchristos     }
6809428323dSchristos     printf("\n");
6819428323dSchristos }
6829428323dSchristos 
6839428323dSchristos void
full_dump_block_zero(partition_map_header * map)6849428323dSchristos full_dump_block_zero(partition_map_header *map)
6859428323dSchristos {
6869428323dSchristos     Block0 *zp;
6879428323dSchristos     DDMap *m;
6889428323dSchristos     int i;
6899428323dSchristos 
6909428323dSchristos     if (map == NULL) {
6919428323dSchristos 	printf("No partition map exists\n");
6929428323dSchristos 	return;
6939428323dSchristos     }
6949428323dSchristos 
6959428323dSchristos     if (map->misc == NULL) {
6969428323dSchristos 	printf("No block zero\n");
6979428323dSchristos 	return;
6989428323dSchristos     }
6999428323dSchristos     zp = map->misc;
7009428323dSchristos 
7019428323dSchristos     printf("             signature: 0x%x\n", zp->sbSig);
7029428323dSchristos     printf("       size of a block: %d\n", zp->sbBlkSize);
703*48a628aeSchristos     printf("      number of blocks: %"PRId32"\n", zp->sbBlkCount);
7049428323dSchristos     printf("           device type: 0x%x\n", zp->sbDevType);
7059428323dSchristos     printf("             device id: 0x%x\n", zp->sbDevId);
706*48a628aeSchristos     printf("                  data: 0x%"PRIx32"\n", zp->sbData);
7079428323dSchristos     printf("          driver count: %d\n", zp->sbDrvrCount);
7089428323dSchristos     m = (DDMap *) zp->sbMap;
7099428323dSchristos     for (i = 0; &m[i].ddType < &zp->sbMap[247]; i++) {
7109428323dSchristos     	if (m[i].ddBlock == 0 && m[i].ddSize == 0 && m[i].ddType == 0) {
7119428323dSchristos     	    break;
7129428323dSchristos     	}
713*48a628aeSchristos 	printf("      driver %3u block: %"PRId32"\n", i+1, m[i].ddBlock);
7149428323dSchristos 	printf("        size in blocks: %d\n", m[i].ddSize);
7159428323dSchristos 	printf("           driver type: 0x%x\n", m[i].ddType);
7169428323dSchristos     }
7179428323dSchristos     printf("remainder of block -");
718*48a628aeSchristos     dump_block((uint8_t *)(void *)&m[i].ddBlock, (&zp->sbMap[247]-((uint16_t *)(void *)&m[i].ddBlock))*2);
7199428323dSchristos }
7209428323dSchristos 
7219428323dSchristos 
7229428323dSchristos void
display_patches(partition_map * entry)7239428323dSchristos display_patches(partition_map *entry)
7249428323dSchristos {
7259428323dSchristos     long long offset;
7269428323dSchristos     MEDIA m;
727*48a628aeSchristos     static uint8_t *patch_block;
7289428323dSchristos     PatchListPtr p;
7299428323dSchristos     PatchDescriptorPtr q;
730*48a628aeSchristos     uint8_t *next;
731*48a628aeSchristos     uint8_t *s;
7329428323dSchristos     int i;
7339428323dSchristos 
7349428323dSchristos     offset = entry->data->dpme_pblock_start;
7359428323dSchristos     m = entry->the_map->m;
7369428323dSchristos     offset = ((long long) entry->data->dpme_pblock_start) * entry->the_map->logical_block;
7379428323dSchristos     if (patch_block == NULL) {
738*48a628aeSchristos 	patch_block = (uint8_t *) malloc(PBLOCK_SIZE);
7399428323dSchristos 	if (patch_block == NULL) {
7409428323dSchristos 	    error(errno, "can't allocate memory for patch block buffer");
7419428323dSchristos 	    return;
7429428323dSchristos 	}
7439428323dSchristos     }
7449428323dSchristos     if (read_media(m, (long long)offset, PBLOCK_SIZE, (char *)patch_block) == 0) {
7459428323dSchristos 	error(errno, "Can't read patch block");
7469428323dSchristos 	return;
7479428323dSchristos     }
7489428323dSchristos     p = (PatchListPtr) patch_block;
7499428323dSchristos     if (p->numPatchBlocks != 1) {
7509428323dSchristos 	i = p->numPatchBlocks;
7519428323dSchristos 	free(patch_block);
752*48a628aeSchristos 	patch_block = (uint8_t *) malloc(PBLOCK_SIZE*i);
7539428323dSchristos 	if (patch_block == NULL) {
7549428323dSchristos 	    error(errno, "can't allocate memory for patch blocks buffer");
7559428323dSchristos 	    return;
7569428323dSchristos 	}
7579428323dSchristos 	s = patch_block + PBLOCK_SIZE*i;
7589428323dSchristos 	while (i > 0) {
7599428323dSchristos 	    s -= PBLOCK_SIZE;
7609428323dSchristos 	    i -= 1;
7619428323dSchristos 	    if (read_media(m, offset+i, PBLOCK_SIZE, (char *)s) == 0) {
7629428323dSchristos 		error(errno, "Can't read patch block %d", i);
7639428323dSchristos 		return;
7649428323dSchristos 	    }
7659428323dSchristos 	}
7669428323dSchristos 	p = (PatchListPtr) patch_block;
7679428323dSchristos     }
7689428323dSchristos     printf("Patch list (%d entries)\n", p->numPatches);
7699428323dSchristos     q = p->thePatch;
7709428323dSchristos     for (i = 0; i < p->numPatches; i++) {
7719428323dSchristos 	printf("%2d signature: '%.4s'\n", i+1, (char *)&q->patchSig);
7729428323dSchristos 	printf("     version: %d.%d\n", q->majorVers, q->minorVers);
773*48a628aeSchristos 	printf("       flags: 0x%"PRIx32"\n", q->flags);
774*48a628aeSchristos 	printf("      offset: %"PRId32"\n", q->patchOffset);
775*48a628aeSchristos 	printf("        size: %"PRId32"\n", q->patchSize);
776*48a628aeSchristos 	printf("         CRC: 0x%"PRIx32"\n", q->patchCRC);
7779428323dSchristos 	printf("        name: '%.*s'\n", q->patchName[0], &q->patchName[1]);
7789428323dSchristos 	printf("      vendor: '%.*s'\n", q->patchVendor[0], &q->patchVendor[1]);
779*48a628aeSchristos 	next = ((uint8_t *)q) + q->patchDescriptorLen;
7809428323dSchristos 	s = &q->patchVendor[q->patchVendor[0]+1];
7819428323dSchristos 	if (next > s) {
7829428323dSchristos 	    printf("remainder of entry -");
7839428323dSchristos 	    dump_block(s, next-s);
7849428323dSchristos 	}
7859428323dSchristos 	q = (PatchDescriptorPtr)next;
7869428323dSchristos     }
7879428323dSchristos }
7889428323dSchristos 
7899428323dSchristos int
get_max_type_string_length(partition_map_header * map)7909428323dSchristos get_max_type_string_length(partition_map_header *map)
7919428323dSchristos {
7929428323dSchristos     partition_map * entry;
7939428323dSchristos     int max;
7949428323dSchristos     int length;
7959428323dSchristos 
7969428323dSchristos     if (map == NULL) {
7979428323dSchristos 	return 0;
7989428323dSchristos     }
7999428323dSchristos 
8009428323dSchristos     max = 0;
8019428323dSchristos 
8029428323dSchristos     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
8039428323dSchristos 	length = strnlen(entry->data->dpme_type, DPISTRLEN);
8049428323dSchristos 	if (length > max) {
8059428323dSchristos 	    max = length;
8069428323dSchristos 	}
8079428323dSchristos     }
8089428323dSchristos 
8099428323dSchristos     return max;
8109428323dSchristos }
8119428323dSchristos 
8129428323dSchristos int
get_max_name_string_length(partition_map_header * map)8139428323dSchristos get_max_name_string_length(partition_map_header *map)
8149428323dSchristos {
8159428323dSchristos     partition_map * entry;
8169428323dSchristos     int max;
8179428323dSchristos     int length;
8189428323dSchristos 
8199428323dSchristos     if (map == NULL) {
8209428323dSchristos 	return 0;
8219428323dSchristos     }
8229428323dSchristos 
8239428323dSchristos     max = 0;
8249428323dSchristos 
8259428323dSchristos     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
8269428323dSchristos 	length = strnlen(entry->data->dpme_name, DPISTRLEN);
8279428323dSchristos 	if (length > max) {
8289428323dSchristos 	    max = length;
8299428323dSchristos 	}
8309428323dSchristos 
8319428323dSchristos 	if (fflag) {
8329428323dSchristos 		if (entry->HFS_name == NULL) {
8339428323dSchristos 		    length = 0;
8349428323dSchristos 		} else {
8359428323dSchristos 		    length = strlen(entry->HFS_name) + 2;
8369428323dSchristos 		}
8379428323dSchristos 		if (length > max) {
8389428323dSchristos 		    max = length;
8399428323dSchristos 		}
8409428323dSchristos 	}
8419428323dSchristos     }
8429428323dSchristos 
8439428323dSchristos     return max;
8449428323dSchristos }
8459428323dSchristos 
8469428323dSchristos int
get_max_base_or_length(partition_map_header * map)8479428323dSchristos get_max_base_or_length(partition_map_header *map)
8489428323dSchristos {
8499428323dSchristos     partition_map * entry;
850*48a628aeSchristos     uint32_t max;
8519428323dSchristos 
8529428323dSchristos     if (map == NULL) {
8539428323dSchristos 	return 0;
8549428323dSchristos     }
8559428323dSchristos 
8569428323dSchristos     max = 0;
8579428323dSchristos 
8589428323dSchristos     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
8599428323dSchristos 	if (entry->data->dpme_pblock_start > max) {
8609428323dSchristos 	    max = entry->data->dpme_pblock_start;
8619428323dSchristos 	}
8629428323dSchristos 	if (entry->data->dpme_pblocks > max) {
8639428323dSchristos 	    max = entry->data->dpme_pblocks;
8649428323dSchristos 	}
8659428323dSchristos 	if (entry->data->dpme_lblock_start > max) {
8669428323dSchristos 	    max = entry->data->dpme_lblock_start;
8679428323dSchristos 	}
8689428323dSchristos 	if (entry->data->dpme_lblocks > max) {
8699428323dSchristos 	    max = entry->data->dpme_lblocks;
8709428323dSchristos 	}
8719428323dSchristos     }
8729428323dSchristos 
8739428323dSchristos     return max;
8749428323dSchristos }
8759428323dSchristos 
8769428323dSchristos void
adjust_value_and_compute_prefix(double * value,int * prefix)8779428323dSchristos adjust_value_and_compute_prefix(double *value, int *prefix)
8789428323dSchristos {
8799428323dSchristos     double bytes;
8809428323dSchristos     int multiplier;
8819428323dSchristos 
8829428323dSchristos     bytes = *value;
8839428323dSchristos     if (bytes < 1024.0) {
8849428323dSchristos 	multiplier = ' ';
8859428323dSchristos     } else {
8869428323dSchristos 	bytes = bytes / 1024.0;
8879428323dSchristos 	if (bytes < 1024.0) {
8889428323dSchristos 	    multiplier = 'K';
8899428323dSchristos 	} else {
8909428323dSchristos 	    bytes = bytes / 1024.0;
8919428323dSchristos 	    if (bytes < 1024.0) {
8929428323dSchristos 		multiplier = 'M';
8939428323dSchristos 	    } else {
8949428323dSchristos 		bytes = bytes / 1024.0;
8959428323dSchristos 		if (bytes < 1024.0) {
8969428323dSchristos 		    multiplier = 'G';
8979428323dSchristos 		} else {
8989428323dSchristos 		    bytes = bytes / 1024.0;
8999428323dSchristos 		    multiplier = 'T';
9009428323dSchristos 		}
9019428323dSchristos 	    }
9029428323dSchristos 	}
9039428323dSchristos     }
9049428323dSchristos     *value = bytes;
9059428323dSchristos     *prefix = multiplier;
9069428323dSchristos }
907