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 int strnlen(char *s, int n); 128 129 130 // 131 // Routines 132 // 133 int 134 dump(char *name) 135 { 136 partition_map_header *map; 137 int junk; 138 139 map = open_partition_map(name, &junk, 0); 140 if (map == NULL) { 141 //error(-1, "No partition map in '%s'", name); 142 return 0; 143 } 144 145 dump_partition_map(map, 1); 146 147 close_partition_map(map); 148 149 return 1; 150 } 151 152 153 void 154 dump_block_zero(partition_map_header *map) 155 { 156 Block0 *p; 157 DDMap *m; 158 int i; 159 double value; 160 int prefix; 161 long t; 162 163 p = map->misc; 164 if (p->sbSig != BLOCK0_SIGNATURE) { 165 return; 166 } 167 168 value = ((double)p->sbBlkCount) * p->sbBlkSize; 169 adjust_value_and_compute_prefix(&value, &prefix); 170 printf("\nDevice block size=%u, Number of Blocks=%lu (%1.1f%c)\n", 171 p->sbBlkSize, p->sbBlkCount, value, prefix); 172 173 printf("DeviceType=0x%x, DeviceId=0x%x\n", 174 p->sbDevType, p->sbDevId); 175 if (p->sbDrvrCount > 0) { 176 printf("Drivers-\n"); 177 m = (DDMap *) p->sbMap; 178 for (i = 0; i < p->sbDrvrCount; i++) { 179 printf("%u: %3u @ %lu, ", i+1, 180 m[i].ddSize, get_align_long(&m[i].ddBlock)); 181 if (map->logical_block != p->sbBlkSize) { 182 t = (m[i].ddSize * p->sbBlkSize) / map->logical_block; 183 printf("(%lu@", t); 184 t = (get_align_long(&m[i].ddBlock) * p->sbBlkSize) 185 / map->logical_block; 186 printf("%lu) ", t); 187 } 188 printf("type=0x%x\n", m[i].ddType); 189 } 190 } 191 printf("\n"); 192 } 193 194 195 void 196 dump_partition_map(partition_map_header *map, int disk_order) 197 { 198 partition_map * entry; 199 int max_type_length; 200 int max_name_length; 201 int digits; 202 203 if (map == NULL) { 204 bad_input("No partition map exists"); 205 return; 206 } 207 printf("\nPartition map (with %d byte blocks) on '%s'\n", 208 map->logical_block, map->name); 209 210 digits = number_of_digits(get_max_base_or_length(map)); 211 if (digits < 6) { 212 digits = 6; 213 } 214 if (aflag) { 215 max_type_length = 4; 216 } else { 217 max_type_length = get_max_type_string_length(map); 218 if (max_type_length < 4) { 219 max_type_length = 4; 220 } 221 } 222 max_name_length = get_max_name_string_length(map); 223 if (max_name_length < 6) { 224 max_name_length = 6; 225 } 226 printf(" #: %*s %-*s %*s %-*s ( size )\n", 227 max_type_length, "type", 228 max_name_length, "name", 229 digits, "length", digits, "base"); 230 231 if (disk_order) { 232 for (entry = map->disk_order; entry != NULL; 233 entry = entry->next_on_disk) { 234 235 dump_partition_entry(entry, max_type_length, max_name_length, digits); 236 } 237 } else { 238 for (entry = map->base_order; entry != NULL; 239 entry = entry->next_by_base) { 240 241 dump_partition_entry(entry, max_type_length, max_name_length, digits); 242 } 243 } 244 dump_block_zero(map); 245 } 246 247 248 void 249 dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits) 250 { 251 partition_map_header *map; 252 int j; 253 DPME *p; 254 const char *s; 255 u32 size; 256 double bytes; 257 int driver; 258 // int kind; 259 char *buf; 260 #if 1 261 BZB *bp; 262 #endif 263 264 map = entry->the_map; 265 p = entry->data; 266 driver = entry->contains_driver? '*': ' '; 267 if (aflag) { 268 s = "????"; 269 for (j = 0; plist[j].abbr != 0; j++) { 270 if (strcmp(p->dpme_type, plist[j].full) == 0) { 271 s = plist[j].abbr; 272 break; 273 } 274 } 275 printf("%2ld: %.4s", entry->disk_address, s); 276 } else { 277 printf("%2ld: %*.32s", entry->disk_address, type_length, p->dpme_type); 278 } 279 280 buf = (char *) malloc(name_length+1); 281 if (entry->HFS_name == NULL || fflag == 0) { 282 strncpy(buf, p->dpme_name, name_length); 283 buf[name_length] = 0; 284 } else { 285 snprintf(buf, name_length + 1, "\"%s\"", entry->HFS_name); 286 } 287 printf("%c%-*.32s ", driver, name_length, buf); 288 free(buf); 289 /* 290 switch (entry->HFS_kind) { 291 case kHFS_std: kind = 'h'; break; 292 case kHFS_embed: kind = 'e'; break; 293 case kHFS_plus: kind = '+'; break; 294 default: 295 case kHFS_not: kind = ' '; break; 296 } 297 printf("%c ", kind); 298 */ 299 300 if (pflag) { 301 printf("%*lu ", digits, p->dpme_pblocks); 302 size = p->dpme_pblocks; 303 } else if (p->dpme_lblocks + p->dpme_lblock_start != p->dpme_pblocks) { 304 printf("%*lu+", digits, p->dpme_lblocks); 305 size = p->dpme_lblocks; 306 } else if (p->dpme_lblock_start != 0) { 307 printf("%*lu ", digits, p->dpme_lblocks); 308 size = p->dpme_lblocks; 309 } else { 310 printf("%*lu ", digits, p->dpme_pblocks); 311 size = p->dpme_pblocks; 312 } 313 if (pflag || p->dpme_lblock_start == 0) { 314 printf("@ %-*lu", digits, p->dpme_pblock_start); 315 } else { 316 printf("@~%-*lu", digits, p->dpme_pblock_start + p->dpme_lblock_start); 317 } 318 319 bytes = ((double)size) * map->logical_block; 320 adjust_value_and_compute_prefix(&bytes, &j); 321 if (j != ' ' && j != 'K') { 322 printf(" (%#5.1f%c)", bytes, j); 323 } 324 325 #if 1 326 // Old A/UX fields that no one pays attention to anymore. 327 bp = (BZB *) (p->dpme_bzb); 328 j = -1; 329 if (bp->bzb_magic == BZBMAGIC) { 330 switch (bp->bzb_type) { 331 case FSTEFS: 332 s = "EFS"; 333 break; 334 case FSTSFS: 335 s = "SFS"; 336 j = 1; 337 break; 338 case FST: 339 default: 340 if (bzb_root_get(bp) != 0) { 341 if (bzb_usr_get(bp) != 0) { 342 s = "RUFS"; 343 } else { 344 s = "RFS"; 345 } 346 j = 0; 347 } else if (bzb_usr_get(bp) != 0) { 348 s = "UFS"; 349 j = 2; 350 } else { 351 s = "FS"; 352 } 353 break; 354 } 355 if (bzb_slice_get(bp) != 0) { 356 printf(" s%1ld %4s", bzb_slice_get(bp)-1, s); 357 } else if (j >= 0) { 358 printf(" S%1d %4s", j, s); 359 } else { 360 printf(" %4s", s); 361 } 362 if (bzb_crit_get(bp) != 0) { 363 printf(" K%1d", bp->bzb_cluster); 364 } else if (j < 0) { 365 printf(" "); 366 } else { 367 printf(" k%1d", bp->bzb_cluster); 368 } 369 if (bp->bzb_mount_point[0] != 0) { 370 printf(" %.64s", bp->bzb_mount_point); 371 } 372 } 373 #endif 374 printf("\n"); 375 } 376 377 378 void 379 show_data_structures(partition_map_header *map) 380 { 381 Block0 *zp; 382 DDMap *m; 383 int i; 384 int j; 385 partition_map * entry; 386 DPME *p; 387 BZB *bp; 388 const char *s; 389 390 if (map == NULL) { 391 printf("No partition map exists\n"); 392 return; 393 } 394 printf("Header:\n"); 395 printf("map %d blocks out of %d, media %lu blocks (%d byte blocks)\n", 396 map->blocks_in_map, map->maximum_in_map, 397 map->media_size, map->logical_block); 398 printf("Map is%s writable", (map->writable)?kStringEmpty:kStringNot); 399 printf(", but%s changed", (map->changed)?kStringEmpty:kStringNot); 400 printf(" and has%s been written\n", (map->written)?kStringEmpty:kStringNot); 401 printf("\n"); 402 403 if (map->misc == NULL) { 404 printf("No block zero\n"); 405 } else { 406 zp = map->misc; 407 408 printf("Block0:\n"); 409 printf("signature 0x%x", zp->sbSig); 410 if (zp->sbSig == BLOCK0_SIGNATURE) { 411 printf("\n"); 412 } else { 413 printf(" should be 0x%x\n", BLOCK0_SIGNATURE); 414 } 415 printf("Block size=%u, Number of Blocks=%lu\n", 416 zp->sbBlkSize, zp->sbBlkCount); 417 printf("DeviceType=0x%x, DeviceId=0x%x, sbData=0x%lx\n", 418 zp->sbDevType, zp->sbDevId, zp->sbData); 419 if (zp->sbDrvrCount == 0) { 420 printf("No drivers\n"); 421 } else { 422 printf("%u driver%s-\n", zp->sbDrvrCount, 423 (zp->sbDrvrCount>1)?"s":kStringEmpty); 424 m = (DDMap *) zp->sbMap; 425 for (i = 0; i < zp->sbDrvrCount; i++) { 426 printf("%u: @ %lu for %u, type=0x%x\n", i+1, 427 get_align_long(&m[i].ddBlock), 428 m[i].ddSize, m[i].ddType); 429 } 430 } 431 } 432 printf("\n"); 433 434 /* 435 u32 dpme_boot_args[32] ; 436 u32 dpme_reserved_3[62] ; 437 */ 438 printf(" #: type length base " 439 "flags (logical)\n"); 440 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 441 p = entry->data; 442 printf("%2ld: %20.32s ", 443 entry->disk_address, p->dpme_type); 444 printf("%7lu @ %-7lu ", p->dpme_pblocks, p->dpme_pblock_start); 445 printf("%c%c%c%c%c%c%c%c%c%c%c%c ", 446 (dpme_valid_get(p))?'V':'.', 447 (dpme_allocated_get(p))?'A':'.', 448 (dpme_in_use_get(p))?'I':'.', 449 (dpme_bootable_get(p))?'B':'.', 450 (dpme_readable_get(p))?'R':'.', 451 (dpme_writable_get(p))?'W':'.', 452 (dpme_os_pic_code_get(p))?'P':'.', 453 (dpme_os_specific_2_get(p))?'2':'.', 454 (dpme_chainable_get(p))?'C':'.', 455 (dpme_diskdriver_get(p))?'D':'.', 456 (bitfield_get(p->dpme_flags, 30, 1))?'M':'.', 457 (bitfield_get(p->dpme_flags, 31, 1))?'X':'.'); 458 if (p->dpme_lblock_start != 0 || p->dpme_pblocks != p->dpme_lblocks) { 459 printf("(%lu @ %lu)", p->dpme_lblocks, p->dpme_lblock_start); 460 } 461 printf("\n"); 462 } 463 printf("\n"); 464 printf(" #: booter bytes load_address " 465 "goto_address checksum processor\n"); 466 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 467 p = entry->data; 468 printf("%2ld: ", entry->disk_address); 469 printf("%7lu ", p->dpme_boot_block); 470 printf("%7lu ", p->dpme_boot_bytes); 471 printf("%8lx ", (u32)p->dpme_load_addr); 472 printf("%8lx ", (u32)p->dpme_load_addr_2); 473 printf("%8lx ", (u32)p->dpme_goto_addr); 474 printf("%8lx ", (u32)p->dpme_goto_addr_2); 475 printf("%8lx ", p->dpme_checksum); 476 printf("%.32s", p->dpme_process_id); 477 printf("\n"); 478 } 479 printf("\n"); 480 /* 481 xx: cccc RU *dd s... 482 */ 483 printf(" #: type RU *slice mount_point (A/UX only fields)\n"); 484 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 485 p = entry->data; 486 printf("%2ld: ", entry->disk_address); 487 488 bp = (BZB *) (p->dpme_bzb); 489 j = -1; 490 if (bp->bzb_magic == BZBMAGIC) { 491 switch (bp->bzb_type) { 492 case FSTEFS: 493 s = "esch"; 494 break; 495 case FSTSFS: 496 s = "swap"; 497 j = 1; 498 break; 499 case FST: 500 default: 501 s = "fsys"; 502 if (bzb_root_get(bp) != 0) { 503 j = 0; 504 } else if (bzb_usr_get(bp) != 0) { 505 j = 2; 506 } 507 break; 508 } 509 printf("%4s ", s); 510 printf("%c%c ", 511 (bzb_root_get(bp))?'R':' ', 512 (bzb_usr_get(bp))?'U':' '); 513 if (bzb_slice_get(bp) != 0) { 514 printf(" %2ld", bzb_slice_get(bp)-1); 515 } else if (j >= 0) { 516 printf(" *%2d", j); 517 } else { 518 printf(" "); 519 } 520 if (bp->bzb_mount_point[0] != 0) { 521 printf(" %.64s", bp->bzb_mount_point); 522 } 523 } 524 printf("\n"); 525 } 526 } 527 528 529 void 530 full_dump_partition_entry(partition_map_header *map, int ix) 531 { 532 partition_map * cur; 533 DPME *p; 534 int i; 535 u32 t; 536 537 cur = find_entry_by_disk_address(ix, map); 538 if (cur == NULL) { 539 printf("No such partition\n"); 540 return; 541 } 542 543 p = cur->data; 544 printf(" signature: 0x%x\n", p->dpme_signature); 545 printf(" reserved1: 0x%x\n", p->dpme_reserved_1); 546 printf(" number of map entries: %ld\n", p->dpme_map_entries); 547 printf(" physical start: %10lu length: %10lu\n", p->dpme_pblock_start, p->dpme_pblocks); 548 printf(" logical start: %10lu length: %10lu\n", p->dpme_lblock_start, p->dpme_lblocks); 549 550 printf(" flags: 0x%lx\n", (u32)p->dpme_flags); 551 printf(" "); 552 if (dpme_valid_get(p)) printf("valid "); 553 if (dpme_allocated_get(p)) printf("alloc "); 554 if (dpme_in_use_get(p)) printf("in-use "); 555 if (dpme_bootable_get(p)) printf("boot "); 556 if (dpme_readable_get(p)) printf("read "); 557 if (dpme_writable_get(p)) printf("write "); 558 if (dpme_os_pic_code_get(p)) printf("pic "); 559 t = p->dpme_flags >> 7; 560 for (i = 7; i <= 31; i++) { 561 if (t & 0x1) { 562 printf("%d ", i); 563 } 564 t = t >> 1; 565 } 566 printf("\n"); 567 568 printf(" name: '%.32s'\n", p->dpme_name); 569 printf(" type: '%.32s'\n", p->dpme_type); 570 571 printf(" boot start block: %10lu\n", p->dpme_boot_block); 572 printf("boot length (in bytes): %10lu\n", p->dpme_boot_bytes); 573 printf(" load address: 0x%08lx 0x%08lx\n", 574 (u32)p->dpme_load_addr, (u32)p->dpme_load_addr_2); 575 printf(" start address: 0x%08lx 0x%08lx\n", 576 (u32)p->dpme_goto_addr, (u32)p->dpme_goto_addr_2); 577 printf(" checksum: 0x%08lx\n", p->dpme_checksum); 578 printf(" processor: '%.32s'\n", p->dpme_process_id); 579 printf("boot args field -"); 580 dump_block((unsigned char *)p->dpme_boot_args, 32*4); 581 printf("dpme_reserved_3 -"); 582 dump_block((unsigned char *)p->dpme_reserved_3, 62*4); 583 } 584 585 586 void 587 dump_block(unsigned char *addr, int len) 588 { 589 int i; 590 int j; 591 int limit1; 592 int limit; 593 #define LINE_LEN 16 594 #define UNIT_LEN 4 595 #define OTHER_LEN 8 596 597 for (i = 0; i < len; i = limit) { 598 limit1 = i + LINE_LEN; 599 if (limit1 > len) { 600 limit = len; 601 } else { 602 limit = limit1; 603 } 604 printf("\n%03x: ", i); 605 for (j = i; j < limit1; j++) { 606 if (j % UNIT_LEN == 0) { 607 printf(" "); 608 } 609 if (j < limit) { 610 printf("%02x", addr[j]); 611 } else { 612 printf(" "); 613 } 614 } 615 printf(" "); 616 for (j = i; j < limit; j++) { 617 if (j % OTHER_LEN == 0) { 618 printf(" "); 619 } 620 if (addr[j] < ' ') { 621 printf("."); 622 } else { 623 printf("%c", addr[j]); 624 } 625 } 626 } 627 printf("\n"); 628 } 629 630 void 631 full_dump_block_zero(partition_map_header *map) 632 { 633 Block0 *zp; 634 DDMap *m; 635 int i; 636 637 if (map == NULL) { 638 printf("No partition map exists\n"); 639 return; 640 } 641 642 if (map->misc == NULL) { 643 printf("No block zero\n"); 644 return; 645 } 646 zp = map->misc; 647 648 printf(" signature: 0x%x\n", zp->sbSig); 649 printf(" size of a block: %d\n", zp->sbBlkSize); 650 printf(" number of blocks: %ld\n", zp->sbBlkCount); 651 printf(" device type: 0x%x\n", zp->sbDevType); 652 printf(" device id: 0x%x\n", zp->sbDevId); 653 printf(" data: 0x%lx\n", zp->sbData); 654 printf(" driver count: %d\n", zp->sbDrvrCount); 655 m = (DDMap *) zp->sbMap; 656 for (i = 0; &m[i].ddType < &zp->sbMap[247]; i++) { 657 if (m[i].ddBlock == 0 && m[i].ddSize == 0 && m[i].ddType == 0) { 658 break; 659 } 660 printf(" driver %3u block: %ld\n", i+1, m[i].ddBlock); 661 printf(" size in blocks: %d\n", m[i].ddSize); 662 printf(" driver type: 0x%x\n", m[i].ddType); 663 } 664 printf("remainder of block -"); 665 dump_block((unsigned char *)&m[i].ddBlock, (&zp->sbMap[247]-((unsigned short *)&m[i].ddBlock))*2); 666 } 667 668 669 void 670 display_patches(partition_map *entry) 671 { 672 long long offset; 673 MEDIA m; 674 static unsigned char *patch_block; 675 PatchListPtr p; 676 PatchDescriptorPtr q; 677 unsigned char *next; 678 unsigned char *s; 679 int i; 680 681 offset = entry->data->dpme_pblock_start; 682 m = entry->the_map->m; 683 offset = ((long long) entry->data->dpme_pblock_start) * entry->the_map->logical_block; 684 if (patch_block == NULL) { 685 patch_block = (unsigned char *) malloc(PBLOCK_SIZE); 686 if (patch_block == NULL) { 687 error(errno, "can't allocate memory for patch block buffer"); 688 return; 689 } 690 } 691 if (read_media(m, (long long)offset, PBLOCK_SIZE, (char *)patch_block) == 0) { 692 error(errno, "Can't read patch block"); 693 return; 694 } 695 p = (PatchListPtr) patch_block; 696 if (p->numPatchBlocks != 1) { 697 i = p->numPatchBlocks; 698 free(patch_block); 699 patch_block = (unsigned char *) malloc(PBLOCK_SIZE*i); 700 if (patch_block == NULL) { 701 error(errno, "can't allocate memory for patch blocks buffer"); 702 return; 703 } 704 s = patch_block + PBLOCK_SIZE*i; 705 while (i > 0) { 706 s -= PBLOCK_SIZE; 707 i -= 1; 708 if (read_media(m, offset+i, PBLOCK_SIZE, (char *)s) == 0) { 709 error(errno, "Can't read patch block %d", i); 710 return; 711 } 712 } 713 p = (PatchListPtr) patch_block; 714 } 715 printf("Patch list (%d entries)\n", p->numPatches); 716 q = p->thePatch; 717 for (i = 0; i < p->numPatches; i++) { 718 printf("%2d signature: '%.4s'\n", i+1, (char *)&q->patchSig); 719 printf(" version: %d.%d\n", q->majorVers, q->minorVers); 720 printf(" flags: 0x%lx\n", q->flags); 721 printf(" offset: %ld\n", q->patchOffset); 722 printf(" size: %ld\n", q->patchSize); 723 printf(" CRC: 0x%lx\n", q->patchCRC); 724 printf(" name: '%.*s'\n", q->patchName[0], &q->patchName[1]); 725 printf(" vendor: '%.*s'\n", q->patchVendor[0], &q->patchVendor[1]); 726 next = ((unsigned char *)q) + q->patchDescriptorLen; 727 s = &q->patchVendor[q->patchVendor[0]+1]; 728 if (next > s) { 729 printf("remainder of entry -"); 730 dump_block(s, next-s); 731 } 732 q = (PatchDescriptorPtr)next; 733 } 734 } 735 736 int 737 strnlen(char *s, int n) 738 { 739 int i; 740 741 for (i = 0; i < n; i++) { 742 if (*s == 0) { 743 break; 744 } 745 s++; 746 } 747 return i; 748 } 749 750 int 751 get_max_type_string_length(partition_map_header *map) 752 { 753 partition_map * entry; 754 int max; 755 int length; 756 757 if (map == NULL) { 758 return 0; 759 } 760 761 max = 0; 762 763 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 764 length = strnlen(entry->data->dpme_type, DPISTRLEN); 765 if (length > max) { 766 max = length; 767 } 768 } 769 770 return max; 771 } 772 773 int 774 get_max_name_string_length(partition_map_header *map) 775 { 776 partition_map * entry; 777 int max; 778 int length; 779 780 if (map == NULL) { 781 return 0; 782 } 783 784 max = 0; 785 786 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 787 length = strnlen(entry->data->dpme_name, DPISTRLEN); 788 if (length > max) { 789 max = length; 790 } 791 792 if (fflag) { 793 if (entry->HFS_name == NULL) { 794 length = 0; 795 } else { 796 length = strlen(entry->HFS_name) + 2; 797 } 798 if (length > max) { 799 max = length; 800 } 801 } 802 } 803 804 return max; 805 } 806 807 int 808 get_max_base_or_length(partition_map_header *map) 809 { 810 partition_map * entry; 811 int max; 812 813 if (map == NULL) { 814 return 0; 815 } 816 817 max = 0; 818 819 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 820 if (entry->data->dpme_pblock_start > max) { 821 max = entry->data->dpme_pblock_start; 822 } 823 if (entry->data->dpme_pblocks > max) { 824 max = entry->data->dpme_pblocks; 825 } 826 if (entry->data->dpme_lblock_start > max) { 827 max = entry->data->dpme_lblock_start; 828 } 829 if (entry->data->dpme_lblocks > max) { 830 max = entry->data->dpme_lblocks; 831 } 832 } 833 834 return max; 835 } 836 837 void 838 adjust_value_and_compute_prefix(double *value, int *prefix) 839 { 840 double bytes; 841 int multiplier; 842 843 bytes = *value; 844 if (bytes < 1024.0) { 845 multiplier = ' '; 846 } else { 847 bytes = bytes / 1024.0; 848 if (bytes < 1024.0) { 849 multiplier = 'K'; 850 } else { 851 bytes = bytes / 1024.0; 852 if (bytes < 1024.0) { 853 multiplier = 'M'; 854 } else { 855 bytes = bytes / 1024.0; 856 if (bytes < 1024.0) { 857 multiplier = 'G'; 858 } else { 859 bytes = bytes / 1024.0; 860 multiplier = 'T'; 861 } 862 } 863 } 864 } 865 *value = bytes; 866 *prefix = multiplier; 867 } 868