1 // 2 // dump.c - dumping partition maps 3 // 4 // Written by Eryk Vershen 5 // 6 7 /* 8 * Copyright 1996,1997,1998 by Apple Computer, Inc. 9 * All Rights Reserved 10 * 11 * Permission to use, copy, modify, and distribute this software and 12 * its documentation for any purpose and without fee is hereby granted, 13 * provided that the above copyright notice appears in all copies and 14 * that both the copyright notice and this permission notice appear in 15 * supporting documentation. 16 * 17 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 * FOR A PARTICULAR PURPOSE. 20 * 21 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 23 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 24 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 25 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26 */ 27 28 // for *printf() 29 #include <stdio.h> 30 31 // for malloc() & free() 32 #include <stdlib.h> 33 34 // for strcmp() 35 #include <string.h> 36 // for O_RDONLY 37 #include <fcntl.h> 38 // for errno 39 #include <errno.h> 40 41 #include "dump.h" 42 #include "pathname.h" 43 #include "io.h" 44 #include "errors.h" 45 46 47 // 48 // Defines 49 // 50 #if DPISTRLEN != 32 51 #error Change in strlen in partition entries! Fix constants 52 #endif 53 54 #define get_align_long(x) (*(x)) 55 56 57 // 58 // Types 59 // 60 typedef struct names { 61 const char *abbr; 62 const char *full; 63 } NAMES; 64 65 typedef unsigned long OSType; 66 67 typedef struct PatchDescriptor { 68 OSType patchSig; 69 unsigned short majorVers; 70 unsigned short minorVers; 71 unsigned long flags; 72 unsigned long patchOffset; 73 unsigned long patchSize; 74 unsigned long patchCRC; 75 unsigned long patchDescriptorLen; 76 unsigned char patchName[33]; 77 unsigned char patchVendor[1]; 78 } PatchDescriptor; 79 typedef PatchDescriptor * PatchDescriptorPtr; 80 81 typedef struct PatchList { 82 unsigned short numPatchBlocks; // number of disk blocks to hold the patch list 83 unsigned short numPatches; // number of patches in list 84 PatchDescriptor thePatch[1]; 85 } PatchList; 86 typedef PatchList *PatchListPtr; 87 88 89 // 90 // Global Constants 91 // 92 NAMES plist[] = { 93 {"Drvr", "Apple_Driver"}, 94 {"Drv4", "Apple_Driver43"}, 95 {"Free", "Apple_Free"}, 96 {"Patc", "Apple_Patches"}, 97 {" HFS", "Apple_HFS"}, 98 {" MFS", "Apple_MFS"}, 99 {"PDOS", "Apple_PRODOS"}, 100 {"junk", "Apple_Scratch"}, 101 {"unix", "Apple_UNIX_SVR2"}, 102 {" map", "Apple_partition_map"}, 103 {0, 0}, 104 }; 105 106 const char * kStringEmpty = ""; 107 const char * kStringNot = " not"; 108 109 110 // 111 // Global Variables 112 // 113 int aflag = AFLAG_DEFAULT; /* abbreviate partition types */ 114 int pflag = PFLAG_DEFAULT; /* show physical limits of partition */ 115 int fflag = FFLAG_DEFAULT; /* show HFS volume names */ 116 117 118 // 119 // Forward declarations 120 // 121 void adjust_value_and_compute_prefix(double *value, int *prefix); 122 void dump_block_zero(partition_map_header *map); 123 void dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits); 124 int get_max_base_or_length(partition_map_header *map); 125 int get_max_name_string_length(partition_map_header *map); 126 int get_max_type_string_length(partition_map_header *map); 127 128 129 // 130 // Routines 131 // 132 int 133 dump(char *name) 134 { 135 partition_map_header *map; 136 int junk; 137 138 map = open_partition_map(name, &junk, 0); 139 if (map == NULL) { 140 //error(-1, "No partition map in '%s'", name); 141 return 0; 142 } 143 144 dump_partition_map(map, 1); 145 146 close_partition_map(map); 147 148 return 1; 149 } 150 151 152 void 153 dump_block_zero(partition_map_header *map) 154 { 155 Block0 *p; 156 DDMap *m; 157 int i; 158 double value; 159 int prefix; 160 long t; 161 162 p = map->misc; 163 if (p->sbSig != BLOCK0_SIGNATURE) { 164 return; 165 } 166 167 value = ((double)p->sbBlkCount) * p->sbBlkSize; 168 adjust_value_and_compute_prefix(&value, &prefix); 169 printf("\nDevice block size=%u, Number of Blocks=%lu (%1.1f%c)\n", 170 p->sbBlkSize, p->sbBlkCount, value, prefix); 171 172 printf("DeviceType=0x%x, DeviceId=0x%x\n", 173 p->sbDevType, p->sbDevId); 174 if (p->sbDrvrCount > 0) { 175 printf("Drivers-\n"); 176 m = (DDMap *) p->sbMap; 177 for (i = 0; i < p->sbDrvrCount; i++) { 178 printf("%u: %3u @ %lu, ", i+1, 179 m[i].ddSize, get_align_long(&m[i].ddBlock)); 180 if (map->logical_block != p->sbBlkSize) { 181 t = (m[i].ddSize * p->sbBlkSize) / map->logical_block; 182 printf("(%lu@", t); 183 t = (get_align_long(&m[i].ddBlock) * p->sbBlkSize) 184 / map->logical_block; 185 printf("%lu) ", t); 186 } 187 printf("type=0x%x\n", m[i].ddType); 188 } 189 } 190 printf("\n"); 191 } 192 193 194 void 195 dump_partition_map(partition_map_header *map, int disk_order) 196 { 197 partition_map * entry; 198 int max_type_length; 199 int max_name_length; 200 int digits; 201 202 if (map == NULL) { 203 bad_input("No partition map exists"); 204 return; 205 } 206 printf("\nPartition map (with %d byte blocks) on '%s'\n", 207 map->logical_block, map->name); 208 209 digits = number_of_digits(get_max_base_or_length(map)); 210 if (digits < 6) { 211 digits = 6; 212 } 213 if (aflag) { 214 max_type_length = 4; 215 } else { 216 max_type_length = get_max_type_string_length(map); 217 if (max_type_length < 4) { 218 max_type_length = 4; 219 } 220 } 221 max_name_length = get_max_name_string_length(map); 222 if (max_name_length < 6) { 223 max_name_length = 6; 224 } 225 printf(" #: %*s %-*s %*s %-*s ( size )\n", 226 max_type_length, "type", 227 max_name_length, "name", 228 digits, "length", digits, "base"); 229 230 if (disk_order) { 231 for (entry = map->disk_order; entry != NULL; 232 entry = entry->next_on_disk) { 233 234 dump_partition_entry(entry, max_type_length, max_name_length, digits); 235 } 236 } else { 237 for (entry = map->base_order; entry != NULL; 238 entry = entry->next_by_base) { 239 240 dump_partition_entry(entry, max_type_length, max_name_length, digits); 241 } 242 } 243 dump_block_zero(map); 244 } 245 246 247 void 248 dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits) 249 { 250 partition_map_header *map; 251 int j; 252 DPME *p; 253 const char *s; 254 u32 size; 255 double bytes; 256 int driver; 257 // int kind; 258 char *buf; 259 #if 1 260 BZB *bp; 261 #endif 262 263 map = entry->the_map; 264 p = entry->data; 265 driver = entry->contains_driver? '*': ' '; 266 if (aflag) { 267 s = "????"; 268 for (j = 0; plist[j].abbr != 0; j++) { 269 if (strcmp(p->dpme_type, plist[j].full) == 0) { 270 s = plist[j].abbr; 271 break; 272 } 273 } 274 printf("%2ld: %.4s", entry->disk_address, s); 275 } else { 276 printf("%2ld: %*.32s", entry->disk_address, type_length, p->dpme_type); 277 } 278 279 buf = (char *) malloc(name_length+1); 280 if (entry->HFS_name == NULL || fflag == 0) { 281 strncpy(buf, p->dpme_name, name_length); 282 buf[name_length] = 0; 283 } else { 284 snprintf(buf, name_length + 1, "\"%s\"", entry->HFS_name); 285 } 286 printf("%c%-*.32s ", driver, name_length, buf); 287 free(buf); 288 /* 289 switch (entry->HFS_kind) { 290 case kHFS_std: kind = 'h'; break; 291 case kHFS_embed: kind = 'e'; break; 292 case kHFS_plus: kind = '+'; break; 293 default: 294 case kHFS_not: kind = ' '; break; 295 } 296 printf("%c ", kind); 297 */ 298 299 if (pflag) { 300 printf("%*lu ", digits, p->dpme_pblocks); 301 size = p->dpme_pblocks; 302 } else if (p->dpme_lblocks + p->dpme_lblock_start != p->dpme_pblocks) { 303 printf("%*lu+", digits, p->dpme_lblocks); 304 size = p->dpme_lblocks; 305 } else if (p->dpme_lblock_start != 0) { 306 printf("%*lu ", digits, p->dpme_lblocks); 307 size = p->dpme_lblocks; 308 } else { 309 printf("%*lu ", digits, p->dpme_pblocks); 310 size = p->dpme_pblocks; 311 } 312 if (pflag || p->dpme_lblock_start == 0) { 313 printf("@ %-*lu", digits, p->dpme_pblock_start); 314 } else { 315 printf("@~%-*lu", digits, p->dpme_pblock_start + p->dpme_lblock_start); 316 } 317 318 bytes = ((double)size) * map->logical_block; 319 adjust_value_and_compute_prefix(&bytes, &j); 320 if (j != ' ' && j != 'K') { 321 printf(" (%#5.1f%c)", bytes, j); 322 } 323 324 #if 1 325 // Old A/UX fields that no one pays attention to anymore. 326 bp = (BZB *) (p->dpme_bzb); 327 j = -1; 328 if (bp->bzb_magic == BZBMAGIC) { 329 switch (bp->bzb_type) { 330 case FSTEFS: 331 s = "EFS"; 332 break; 333 case FSTSFS: 334 s = "SFS"; 335 j = 1; 336 break; 337 case FST: 338 default: 339 if (bzb_root_get(bp) != 0) { 340 if (bzb_usr_get(bp) != 0) { 341 s = "RUFS"; 342 } else { 343 s = "RFS"; 344 } 345 j = 0; 346 } else if (bzb_usr_get(bp) != 0) { 347 s = "UFS"; 348 j = 2; 349 } else { 350 s = "FS"; 351 } 352 break; 353 } 354 if (bzb_slice_get(bp) != 0) { 355 printf(" s%1ld %4s", bzb_slice_get(bp)-1, s); 356 } else if (j >= 0) { 357 printf(" S%1d %4s", j, s); 358 } else { 359 printf(" %4s", s); 360 } 361 if (bzb_crit_get(bp) != 0) { 362 printf(" K%1d", bp->bzb_cluster); 363 } else if (j < 0) { 364 printf(" "); 365 } else { 366 printf(" k%1d", bp->bzb_cluster); 367 } 368 if (bp->bzb_mount_point[0] != 0) { 369 printf(" %.64s", bp->bzb_mount_point); 370 } 371 } 372 #endif 373 printf("\n"); 374 } 375 376 377 void 378 show_data_structures(partition_map_header *map) 379 { 380 Block0 *zp; 381 DDMap *m; 382 int i; 383 int j; 384 partition_map * entry; 385 DPME *p; 386 BZB *bp; 387 const char *s; 388 389 if (map == NULL) { 390 printf("No partition map exists\n"); 391 return; 392 } 393 printf("Header:\n"); 394 printf("map %d blocks out of %d, media %lu blocks (%d byte blocks)\n", 395 map->blocks_in_map, map->maximum_in_map, 396 map->media_size, map->logical_block); 397 printf("Map is%s writable", (map->writable)?kStringEmpty:kStringNot); 398 printf(", but%s changed", (map->changed)?kStringEmpty:kStringNot); 399 printf(" and has%s been written\n", (map->written)?kStringEmpty:kStringNot); 400 printf("\n"); 401 402 if (map->misc == NULL) { 403 printf("No block zero\n"); 404 } else { 405 zp = map->misc; 406 407 printf("Block0:\n"); 408 printf("signature 0x%x", zp->sbSig); 409 if (zp->sbSig == BLOCK0_SIGNATURE) { 410 printf("\n"); 411 } else { 412 printf(" should be 0x%x\n", BLOCK0_SIGNATURE); 413 } 414 printf("Block size=%u, Number of Blocks=%lu\n", 415 zp->sbBlkSize, zp->sbBlkCount); 416 printf("DeviceType=0x%x, DeviceId=0x%x, sbData=0x%lx\n", 417 zp->sbDevType, zp->sbDevId, zp->sbData); 418 if (zp->sbDrvrCount == 0) { 419 printf("No drivers\n"); 420 } else { 421 printf("%u driver%s-\n", zp->sbDrvrCount, 422 (zp->sbDrvrCount>1)?"s":kStringEmpty); 423 m = (DDMap *) zp->sbMap; 424 for (i = 0; i < zp->sbDrvrCount; i++) { 425 printf("%u: @ %lu for %u, type=0x%x\n", i+1, 426 get_align_long(&m[i].ddBlock), 427 m[i].ddSize, m[i].ddType); 428 } 429 } 430 } 431 printf("\n"); 432 433 /* 434 u32 dpme_boot_args[32] ; 435 u32 dpme_reserved_3[62] ; 436 */ 437 printf(" #: type length base " 438 "flags (logical)\n"); 439 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 440 p = entry->data; 441 printf("%2ld: %20.32s ", 442 entry->disk_address, p->dpme_type); 443 printf("%7lu @ %-7lu ", p->dpme_pblocks, p->dpme_pblock_start); 444 printf("%c%c%c%c%c%c%c%c%c%c%c%c ", 445 (dpme_valid_get(p))?'V':'.', 446 (dpme_allocated_get(p))?'A':'.', 447 (dpme_in_use_get(p))?'I':'.', 448 (dpme_bootable_get(p))?'B':'.', 449 (dpme_readable_get(p))?'R':'.', 450 (dpme_writable_get(p))?'W':'.', 451 (dpme_os_pic_code_get(p))?'P':'.', 452 (dpme_os_specific_2_get(p))?'2':'.', 453 (dpme_chainable_get(p))?'C':'.', 454 (dpme_diskdriver_get(p))?'D':'.', 455 (bitfield_get(p->dpme_flags, 30, 1))?'M':'.', 456 (bitfield_get(p->dpme_flags, 31, 1))?'X':'.'); 457 if (p->dpme_lblock_start != 0 || p->dpme_pblocks != p->dpme_lblocks) { 458 printf("(%lu @ %lu)", p->dpme_lblocks, p->dpme_lblock_start); 459 } 460 printf("\n"); 461 } 462 printf("\n"); 463 printf(" #: booter bytes load_address " 464 "goto_address checksum processor\n"); 465 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 466 p = entry->data; 467 printf("%2ld: ", entry->disk_address); 468 printf("%7lu ", p->dpme_boot_block); 469 printf("%7lu ", p->dpme_boot_bytes); 470 printf("%8lx ", (u32)p->dpme_load_addr); 471 printf("%8lx ", (u32)p->dpme_load_addr_2); 472 printf("%8lx ", (u32)p->dpme_goto_addr); 473 printf("%8lx ", (u32)p->dpme_goto_addr_2); 474 printf("%8lx ", p->dpme_checksum); 475 printf("%.32s", p->dpme_process_id); 476 printf("\n"); 477 } 478 printf("\n"); 479 /* 480 xx: cccc RU *dd s... 481 */ 482 printf(" #: type RU *slice mount_point (A/UX only fields)\n"); 483 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 484 p = entry->data; 485 printf("%2ld: ", entry->disk_address); 486 487 bp = (BZB *) (p->dpme_bzb); 488 j = -1; 489 if (bp->bzb_magic == BZBMAGIC) { 490 switch (bp->bzb_type) { 491 case FSTEFS: 492 s = "esch"; 493 break; 494 case FSTSFS: 495 s = "swap"; 496 j = 1; 497 break; 498 case FST: 499 default: 500 s = "fsys"; 501 if (bzb_root_get(bp) != 0) { 502 j = 0; 503 } else if (bzb_usr_get(bp) != 0) { 504 j = 2; 505 } 506 break; 507 } 508 printf("%4s ", s); 509 printf("%c%c ", 510 (bzb_root_get(bp))?'R':' ', 511 (bzb_usr_get(bp))?'U':' '); 512 if (bzb_slice_get(bp) != 0) { 513 printf(" %2ld", bzb_slice_get(bp)-1); 514 } else if (j >= 0) { 515 printf(" *%2d", j); 516 } else { 517 printf(" "); 518 } 519 if (bp->bzb_mount_point[0] != 0) { 520 printf(" %.64s", bp->bzb_mount_point); 521 } 522 } 523 printf("\n"); 524 } 525 } 526 527 528 void 529 full_dump_partition_entry(partition_map_header *map, int ix) 530 { 531 partition_map * cur; 532 DPME *p; 533 int i; 534 u32 t; 535 536 cur = find_entry_by_disk_address(ix, map); 537 if (cur == NULL) { 538 printf("No such partition\n"); 539 return; 540 } 541 542 p = cur->data; 543 printf(" signature: 0x%x\n", p->dpme_signature); 544 printf(" reserved1: 0x%x\n", p->dpme_reserved_1); 545 printf(" number of map entries: %ld\n", p->dpme_map_entries); 546 printf(" physical start: %10lu length: %10lu\n", p->dpme_pblock_start, p->dpme_pblocks); 547 printf(" logical start: %10lu length: %10lu\n", p->dpme_lblock_start, p->dpme_lblocks); 548 549 printf(" flags: 0x%lx\n", (u32)p->dpme_flags); 550 printf(" "); 551 if (dpme_valid_get(p)) printf("valid "); 552 if (dpme_allocated_get(p)) printf("alloc "); 553 if (dpme_in_use_get(p)) printf("in-use "); 554 if (dpme_bootable_get(p)) printf("boot "); 555 if (dpme_readable_get(p)) printf("read "); 556 if (dpme_writable_get(p)) printf("write "); 557 if (dpme_os_pic_code_get(p)) printf("pic "); 558 t = p->dpme_flags >> 7; 559 for (i = 7; i <= 31; i++) { 560 if (t & 0x1) { 561 printf("%d ", i); 562 } 563 t = t >> 1; 564 } 565 printf("\n"); 566 567 printf(" name: '%.32s'\n", p->dpme_name); 568 printf(" type: '%.32s'\n", p->dpme_type); 569 570 printf(" boot start block: %10lu\n", p->dpme_boot_block); 571 printf("boot length (in bytes): %10lu\n", p->dpme_boot_bytes); 572 printf(" load address: 0x%08lx 0x%08lx\n", 573 (u32)p->dpme_load_addr, (u32)p->dpme_load_addr_2); 574 printf(" start address: 0x%08lx 0x%08lx\n", 575 (u32)p->dpme_goto_addr, (u32)p->dpme_goto_addr_2); 576 printf(" checksum: 0x%08lx\n", p->dpme_checksum); 577 printf(" processor: '%.32s'\n", p->dpme_process_id); 578 printf("boot args field -"); 579 dump_block((unsigned char *)p->dpme_boot_args, 32*4); 580 printf("dpme_reserved_3 -"); 581 dump_block((unsigned char *)p->dpme_reserved_3, 62*4); 582 } 583 584 585 void 586 dump_block(unsigned char *addr, int len) 587 { 588 int i; 589 int j; 590 int limit1; 591 int limit; 592 #define LINE_LEN 16 593 #define UNIT_LEN 4 594 #define OTHER_LEN 8 595 596 for (i = 0; i < len; i = limit) { 597 limit1 = i + LINE_LEN; 598 if (limit1 > len) { 599 limit = len; 600 } else { 601 limit = limit1; 602 } 603 printf("\n%03x: ", i); 604 for (j = i; j < limit1; j++) { 605 if (j % UNIT_LEN == 0) { 606 printf(" "); 607 } 608 if (j < limit) { 609 printf("%02x", addr[j]); 610 } else { 611 printf(" "); 612 } 613 } 614 printf(" "); 615 for (j = i; j < limit; j++) { 616 if (j % OTHER_LEN == 0) { 617 printf(" "); 618 } 619 if (addr[j] < ' ') { 620 printf("."); 621 } else { 622 printf("%c", addr[j]); 623 } 624 } 625 } 626 printf("\n"); 627 } 628 629 void 630 full_dump_block_zero(partition_map_header *map) 631 { 632 Block0 *zp; 633 DDMap *m; 634 int i; 635 636 if (map == NULL) { 637 printf("No partition map exists\n"); 638 return; 639 } 640 641 if (map->misc == NULL) { 642 printf("No block zero\n"); 643 return; 644 } 645 zp = map->misc; 646 647 printf(" signature: 0x%x\n", zp->sbSig); 648 printf(" size of a block: %d\n", zp->sbBlkSize); 649 printf(" number of blocks: %ld\n", zp->sbBlkCount); 650 printf(" device type: 0x%x\n", zp->sbDevType); 651 printf(" device id: 0x%x\n", zp->sbDevId); 652 printf(" data: 0x%lx\n", zp->sbData); 653 printf(" driver count: %d\n", zp->sbDrvrCount); 654 m = (DDMap *) zp->sbMap; 655 for (i = 0; &m[i].ddType < &zp->sbMap[247]; i++) { 656 if (m[i].ddBlock == 0 && m[i].ddSize == 0 && m[i].ddType == 0) { 657 break; 658 } 659 printf(" driver %3u block: %ld\n", i+1, m[i].ddBlock); 660 printf(" size in blocks: %d\n", m[i].ddSize); 661 printf(" driver type: 0x%x\n", m[i].ddType); 662 } 663 printf("remainder of block -"); 664 dump_block((unsigned char *)&m[i].ddBlock, (&zp->sbMap[247]-((unsigned short *)&m[i].ddBlock))*2); 665 } 666 667 668 void 669 display_patches(partition_map *entry) 670 { 671 long long offset; 672 MEDIA m; 673 static unsigned char *patch_block; 674 PatchListPtr p; 675 PatchDescriptorPtr q; 676 unsigned char *next; 677 unsigned char *s; 678 int i; 679 680 offset = entry->data->dpme_pblock_start; 681 m = entry->the_map->m; 682 offset = ((long long) entry->data->dpme_pblock_start) * entry->the_map->logical_block; 683 if (patch_block == NULL) { 684 patch_block = (unsigned char *) malloc(PBLOCK_SIZE); 685 if (patch_block == NULL) { 686 error(errno, "can't allocate memory for patch block buffer"); 687 return; 688 } 689 } 690 if (read_media(m, (long long)offset, PBLOCK_SIZE, (char *)patch_block) == 0) { 691 error(errno, "Can't read patch block"); 692 return; 693 } 694 p = (PatchListPtr) patch_block; 695 if (p->numPatchBlocks != 1) { 696 i = p->numPatchBlocks; 697 free(patch_block); 698 patch_block = (unsigned char *) malloc(PBLOCK_SIZE*i); 699 if (patch_block == NULL) { 700 error(errno, "can't allocate memory for patch blocks buffer"); 701 return; 702 } 703 s = patch_block + PBLOCK_SIZE*i; 704 while (i > 0) { 705 s -= PBLOCK_SIZE; 706 i -= 1; 707 if (read_media(m, offset+i, PBLOCK_SIZE, (char *)s) == 0) { 708 error(errno, "Can't read patch block %d", i); 709 return; 710 } 711 } 712 p = (PatchListPtr) patch_block; 713 } 714 printf("Patch list (%d entries)\n", p->numPatches); 715 q = p->thePatch; 716 for (i = 0; i < p->numPatches; i++) { 717 printf("%2d signature: '%.4s'\n", i+1, (char *)&q->patchSig); 718 printf(" version: %d.%d\n", q->majorVers, q->minorVers); 719 printf(" flags: 0x%lx\n", q->flags); 720 printf(" offset: %ld\n", q->patchOffset); 721 printf(" size: %ld\n", q->patchSize); 722 printf(" CRC: 0x%lx\n", q->patchCRC); 723 printf(" name: '%.*s'\n", q->patchName[0], &q->patchName[1]); 724 printf(" vendor: '%.*s'\n", q->patchVendor[0], &q->patchVendor[1]); 725 next = ((unsigned char *)q) + q->patchDescriptorLen; 726 s = &q->patchVendor[q->patchVendor[0]+1]; 727 if (next > s) { 728 printf("remainder of entry -"); 729 dump_block(s, next-s); 730 } 731 q = (PatchDescriptorPtr)next; 732 } 733 } 734 735 int 736 get_max_type_string_length(partition_map_header *map) 737 { 738 partition_map * entry; 739 int max; 740 int length; 741 742 if (map == NULL) { 743 return 0; 744 } 745 746 max = 0; 747 748 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 749 length = strnlen(entry->data->dpme_type, DPISTRLEN); 750 if (length > max) { 751 max = length; 752 } 753 } 754 755 return max; 756 } 757 758 int 759 get_max_name_string_length(partition_map_header *map) 760 { 761 partition_map * entry; 762 int max; 763 int length; 764 765 if (map == NULL) { 766 return 0; 767 } 768 769 max = 0; 770 771 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 772 length = strnlen(entry->data->dpme_name, DPISTRLEN); 773 if (length > max) { 774 max = length; 775 } 776 777 if (fflag) { 778 if (entry->HFS_name == NULL) { 779 length = 0; 780 } else { 781 length = strlen(entry->HFS_name) + 2; 782 } 783 if (length > max) { 784 max = length; 785 } 786 } 787 } 788 789 return max; 790 } 791 792 int 793 get_max_base_or_length(partition_map_header *map) 794 { 795 partition_map * entry; 796 int max; 797 798 if (map == NULL) { 799 return 0; 800 } 801 802 max = 0; 803 804 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 805 if (entry->data->dpme_pblock_start > max) { 806 max = entry->data->dpme_pblock_start; 807 } 808 if (entry->data->dpme_pblocks > max) { 809 max = entry->data->dpme_pblocks; 810 } 811 if (entry->data->dpme_lblock_start > max) { 812 max = entry->data->dpme_lblock_start; 813 } 814 if (entry->data->dpme_lblocks > max) { 815 max = entry->data->dpme_lblocks; 816 } 817 } 818 819 return max; 820 } 821 822 void 823 adjust_value_and_compute_prefix(double *value, int *prefix) 824 { 825 double bytes; 826 int multiplier; 827 828 bytes = *value; 829 if (bytes < 1024.0) { 830 multiplier = ' '; 831 } else { 832 bytes = bytes / 1024.0; 833 if (bytes < 1024.0) { 834 multiplier = 'K'; 835 } else { 836 bytes = bytes / 1024.0; 837 if (bytes < 1024.0) { 838 multiplier = 'M'; 839 } else { 840 bytes = bytes / 1024.0; 841 if (bytes < 1024.0) { 842 multiplier = 'G'; 843 } else { 844 bytes = bytes / 1024.0; 845 multiplier = 'T'; 846 } 847 } 848 } 849 } 850 *value = bytes; 851 *prefix = multiplier; 852 } 853