1 // 2 // pdisk - an editor for Apple format partition tables 3 // 4 // Written by Eryk Vershen 5 // 6 // Still under development (as of 15 January 1998) 7 // 8 9 /* 10 * Copyright 1996,1997,1998 by Apple Computer, Inc. 11 * All Rights Reserved 12 * 13 * Permission to use, copy, modify, and distribute this software and 14 * its documentation for any purpose and without fee is hereby granted, 15 * provided that the above copyright notice appears in all copies and 16 * that both the copyright notice and this permission notice appear in 17 * supporting documentation. 18 * 19 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE. 22 * 23 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 25 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 26 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 27 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 28 */ 29 30 // for printf() 31 #include <stdio.h> 32 33 // for malloc() & free() 34 #include <stdlib.h> 35 #include <unistd.h> 36 37 // for strncpy() & strlen() 38 #include <string.h> 39 // for O_RDONLY 40 #include <fcntl.h> 41 // for errno 42 #include <errno.h> 43 44 #include "pdisk.h" 45 #include "io.h" 46 #include "partition_map.h" 47 #include "pathname.h" 48 #include "hfs_misc.h" 49 #include "errors.h" 50 #include "dump.h" 51 #include "validate.h" 52 #include "version.h" 53 #include "util.h" 54 55 56 // 57 // Defines 58 // 59 #define ARGV_CHUNK 5 60 #define CFLAG_DEFAULT 0 61 #define DFLAG_DEFAULT 0 62 #define HFLAG_DEFAULT 0 63 #define INTERACT_DEFAULT 0 64 #define LFLAG_DEFAULT 0 65 #define RFLAG_DEFAULT 0 66 #define VFLAG_DEFAULT 0 67 68 69 // 70 // Types 71 // 72 73 74 // 75 // Global Constants 76 // 77 enum getopt_values { 78 kLongOption = 0, 79 kBadOption = '?', 80 kOptionArg = 1000, 81 kListOption = 1001, 82 kLogicalOption = 1002 83 }; 84 85 86 // 87 // Global Variables 88 // 89 int lflag = LFLAG_DEFAULT; /* list the device */ 90 char *lfile; /* list */ 91 int vflag = VFLAG_DEFAULT; /* show version */ 92 int hflag = HFLAG_DEFAULT; /* show help */ 93 int dflag = DFLAG_DEFAULT; /* turn on debugging commands and printout */ 94 int rflag = RFLAG_DEFAULT; /* open device read Only */ 95 int interactive = INTERACT_DEFAULT; 96 int cflag = CFLAG_DEFAULT; /* compute device size */ 97 98 static int first_get = 1; 99 100 101 // 102 // Forward declarations 103 // 104 void do_change_map_size(partition_map_header *map); 105 #ifdef __m68k__ 106 void do_update_dpme(partition_map *entry); 107 #endif 108 void do_create_partition(partition_map_header *map, int get_type); 109 void do_delete_partition(partition_map_header *map); 110 void do_display_block(partition_map_header *map, char *alt_name); 111 void do_display_entry(partition_map_header *map); 112 void do_examine_patch_partition(partition_map_header *map); 113 int do_expert(partition_map_header *map, char *name); 114 void do_rename_partition(partition_map_header *map); 115 void do_change_type(partition_map_header *map); 116 void do_reorder(partition_map_header *map); 117 void do_write_partition_map(partition_map_header *map); 118 void edit(char *name, int ask_logical_size); 119 int get_base_argument(long *number, partition_map_header *map); 120 int get_command_line(int *argc, char ***argv); 121 int get_size_argument(long *number, partition_map_header *map); 122 int get_options(int argc, char **argv); 123 void interact(void); 124 void print_edit_notes(void); 125 void print_expert_notes(void); 126 127 128 // 129 // Routines 130 // 131 int 132 main(int argc, char **argv) 133 { 134 int name_index; 135 char *versionstr; 136 137 init_program_name(argv); 138 139 if (sizeof(DPME) != PBLOCK_SIZE) { 140 fatal(-1, "Size of partition map entry (%d) " 141 "is not equal to block size (%d)\n", 142 sizeof(DPME), PBLOCK_SIZE); 143 } 144 if (sizeof(Block0) != PBLOCK_SIZE) { 145 fatal(-1, "Size of block zero structure (%d) " 146 "is not equal to block size (%d)\n", 147 sizeof(Block0), PBLOCK_SIZE); 148 } 149 versionstr = (char *)get_version_string(); 150 if (versionstr) { 151 if (strcmp(VERSION, versionstr) != 0) { 152 fatal(-1, "Version string static form (%s) does not match dynamic form (%s)\n", 153 VERSION, versionstr); 154 } 155 free(versionstr); 156 } 157 158 name_index = get_options(argc, argv); 159 160 if (vflag) { 161 printf("version " VERSION " (" RELEASE_DATE ")\n"); 162 } 163 if (hflag) { 164 do_help(); 165 } else if (interactive) { 166 interact(); 167 } else if (lflag) { 168 if (lfile != NULL) { 169 dump(lfile); 170 } else if (name_index < argc) { 171 while (name_index < argc) { 172 dump(argv[name_index++]); 173 } 174 } else { 175 do_help(); 176 } 177 } else if (name_index < argc) { 178 while (name_index < argc) { 179 edit(argv[name_index++], 0); 180 } 181 } else if (!vflag) { 182 do_help(); 183 } 184 return 0; 185 } 186 187 188 void 189 interact() 190 { 191 char *name; 192 int command; 193 int ask_logical_size; 194 195 while (get_command("Top level command (? for help): ", first_get, &command)) { 196 first_get = 0; 197 ask_logical_size = 0; 198 199 switch (command) { 200 case '?': 201 // fall through 202 case 'H': 203 case 'h': 204 printf("Commands are:\n"); 205 printf(" h print help\n"); 206 printf(" v print the version number and release date\n"); 207 printf(" l list device's map\n"); 208 printf(" e edit device's map\n"); 209 printf(" E (edit map with specified block size)\n"); 210 printf(" r toggle readonly flag\n"); 211 printf(" f toggle show filesystem name flag\n"); 212 if (dflag) { 213 printf(" a toggle abbreviate flag\n"); 214 printf(" p toggle physical flag\n"); 215 printf(" c toggle compute size flag\n"); 216 printf(" d toggle debug flag\n"); 217 printf(" x examine block n of device\n"); 218 } 219 printf(" q quit the program\n"); 220 break; 221 case 'Q': 222 case 'q': 223 return; 224 break; 225 case 'V': 226 case 'v': 227 printf("version " VERSION " (" RELEASE_DATE ")\n"); 228 break; 229 case 'l': 230 if (get_string_argument("Name of device: ", &name, 1) == 0) { 231 bad_input("Bad name"); 232 break; 233 } 234 dump(name); 235 free(name); 236 break; 237 case 'E': 238 ask_logical_size = 1; 239 case 'e': 240 if (get_string_argument("Name of device: ", &name, 1) == 0) { 241 bad_input("Bad name"); 242 break; 243 } 244 edit(name, ask_logical_size); 245 free(name); 246 break; 247 case 'R': 248 case 'r': 249 if (rflag) { 250 rflag = 0; 251 } else { 252 rflag = 1; 253 } 254 printf("Now in %s mode.\n", (rflag)?"readonly":"read/write"); 255 break; 256 case 'F': 257 case 'f': 258 if (fflag) { 259 fflag = 0; 260 } else { 261 fflag = 1; 262 } 263 printf("Now in show %s name mode.\n", (fflag)?"filesystem":"partition"); 264 break; 265 case 'A': 266 case 'a': 267 if (dflag) { 268 if (aflag) { 269 aflag = 0; 270 } else { 271 aflag = 1; 272 } 273 printf("Now in %s mode.\n", (aflag)?"abbreviate":"full type"); 274 } else { 275 goto do_error; 276 } 277 break; 278 case 'P': 279 case 'p': 280 if (dflag) { 281 if (pflag) { 282 pflag = 0; 283 } else { 284 pflag = 1; 285 } 286 printf("Now in %s mode.\n", (pflag)?"physical":"logical"); 287 } else { 288 goto do_error; 289 } 290 break; 291 case 'D': 292 case 'd': 293 if (dflag) { 294 dflag = 0; 295 } else { 296 dflag = 1; 297 } 298 printf("Now in %s mode.\n", (dflag)?"debug":"normal"); 299 break; 300 case 'C': 301 case 'c': 302 if (dflag) { 303 if (cflag) { 304 cflag = 0; 305 } else { 306 cflag = 1; 307 } 308 printf("Now in %s device size mode.\n", (cflag)?"always compute":"use existing"); 309 } else { 310 goto do_error; 311 } 312 break; 313 case 'X': 314 case 'x': 315 if (dflag) { 316 do_display_block(0, 0); 317 } else { 318 goto do_error; 319 } 320 break; 321 default: 322 do_error: 323 bad_input("No such command (%c)", command); 324 break; 325 } 326 } 327 } 328 329 330 int 331 get_options(int argc, char **argv) 332 { 333 int c; 334 extern int optind; 335 extern char *optarg; 336 int flag = 0; 337 338 lflag = LFLAG_DEFAULT; 339 lfile = NULL; 340 vflag = VFLAG_DEFAULT; 341 hflag = HFLAG_DEFAULT; 342 dflag = DFLAG_DEFAULT; 343 rflag = RFLAG_DEFAULT; 344 aflag = AFLAG_DEFAULT; 345 pflag = PFLAG_DEFAULT; 346 interactive = INTERACT_DEFAULT; 347 cflag = CFLAG_DEFAULT; 348 349 optind = 1; // reset option scanner logic 350 while ((c = getopt(argc, argv, "hlvdric")) != -1) { 351 switch (c) { 352 case 'h': 353 hflag = (HFLAG_DEFAULT)?0:1; 354 break; 355 case 'l': 356 lflag = (LFLAG_DEFAULT)?0:1; 357 break; 358 case 'v': 359 vflag = (VFLAG_DEFAULT)?0:1; 360 break; 361 case 'd': 362 dflag = (DFLAG_DEFAULT)?0:1; 363 break; 364 case 'c': 365 cflag = (CFLAG_DEFAULT)?0:1; 366 break; 367 case 'r': 368 rflag = (RFLAG_DEFAULT)?0:1; 369 break; 370 case 'i': 371 interactive = (INTERACT_DEFAULT)?0:1; 372 break; 373 case 'a': 374 aflag = (AFLAG_DEFAULT)?0:1; 375 break; 376 case kLogicalOption: 377 pflag = (PFLAG_DEFAULT)?0:1; 378 break; 379 default: 380 flag = 1; 381 break; 382 } 383 } 384 if (flag) { 385 usage("bad arguments"); 386 } 387 return optind; 388 } 389 390 391 void 392 print_edit_notes() 393 { 394 printf("Notes:\n"); 395 printf(" Base and length fields are blocks, which vary in size between media.\n"); 396 printf(" The base field can be <nth>p; i.e. use the base of the nth partition.\n"); 397 printf(" The length field can be a length followed by k, m, g or t to indicate\n"); 398 printf(" kilo, mega, giga, or tera bytes; also the length can be <nth>p; i.e. use\n"); 399 printf(" the length of the nth partition.\n"); 400 printf(" The name of a partition is descriptive text.\n"); 401 printf("\n"); 402 } 403 404 405 // 406 // Edit the file 407 // 408 void 409 edit(char *name, int ask_logical_size) 410 { 411 partition_map_header *map; 412 int command; 413 int order; 414 int get_type; 415 int valid_file; 416 417 map = open_partition_map(name, &valid_file, ask_logical_size); 418 if (!valid_file) { 419 return; 420 } 421 422 printf("Edit %s -\n", name); 423 424 while (get_command("Command (? for help): ", first_get, &command)) { 425 first_get = 0; 426 order = 1; 427 get_type = 0; 428 429 switch (command) { 430 case '?': 431 print_edit_notes(); 432 // fall through 433 case 'H': 434 case 'h': 435 printf("Commands are:\n"); 436 printf(" C (create with type also specified)\n"); 437 printf(" c create new partition (standard OpenBSD root)\n"); 438 printf(" d delete a partition\n"); 439 printf(" h help\n"); 440 printf(" i initialize partition map\n"); 441 printf(" n (re)name a partition\n"); 442 printf(" P (print ordered by base address)\n"); 443 printf(" p print the partition table\n"); 444 printf(" q quit editing\n"); 445 printf(" r reorder partition entry in map\n"); 446 printf(" s change size of partition map\n"); 447 printf(" t change a partition's type\n"); 448 if (!rflag) { 449 printf(" w write the partition table\n"); 450 } 451 if (dflag) { 452 printf(" x extra extensions for experts\n"); 453 } 454 break; 455 case 'P': 456 order = 0; 457 // fall through 458 case 'p': 459 dump_partition_map(map, order); 460 break; 461 case 'Q': 462 case 'q': 463 if (map && map->changed) { 464 if (get_okay("Discard changes? [n/y]: ", 0) != 1) { 465 break; 466 } 467 } 468 flush_to_newline(1); 469 goto finis; 470 break; 471 case 'I': 472 case 'i': 473 map = init_partition_map(name, map); 474 break; 475 case 'C': 476 get_type = 1; 477 // fall through 478 case 'c': 479 do_create_partition(map, get_type); 480 break; 481 case 'N': 482 case 'n': 483 do_rename_partition(map); 484 break; 485 case 'D': 486 case 'd': 487 do_delete_partition(map); 488 break; 489 case 'R': 490 case 'r': 491 do_reorder(map); 492 break; 493 case 'S': 494 case 's': 495 do_change_map_size(map); 496 break; 497 case 'T': 498 case 't': 499 do_change_type(map); 500 break; 501 case 'X': 502 case 'x': 503 if (!dflag) { 504 goto do_error; 505 } else if (do_expert(map, name)) { 506 flush_to_newline(1); 507 goto finis; 508 } 509 break; 510 case 'W': 511 case 'w': 512 if (!rflag) { 513 do_write_partition_map(map); 514 } else { 515 goto do_error; 516 } 517 break; 518 default: 519 do_error: 520 bad_input("No such command (%c)", command); 521 break; 522 } 523 } 524 finis: 525 526 close_partition_map(map); 527 } 528 529 #ifdef __m68k__ 530 void 531 do_update_dpme(partition_map *entry) 532 { 533 int slice = 0; 534 if (!entry) return; 535 dpme_init_flags(entry->data); 536 entry->HFS_name = get_HFS_name(entry, &entry->HFS_kind); 537 if (istrncmp(entry->data->dpme_type, kUnixType, DPISTRLEN) == 0) { 538 printf("Available partition slices for %s:\n",entry->data->dpme_type); 539 printf(" a root partition\n"); 540 printf(" b swap partition\n"); 541 printf(" c do not set any bzb bits\n"); 542 printf(" g user partition\n"); 543 printf("Other lettered values will create user partitions\n"); 544 get_command("Select a slice for default bzb values: ",0,&slice); 545 } 546 bzb_init_slice((BZB *)entry->data->dpme_bzb,slice); 547 entry->the_map->changed = 1; 548 } 549 #endif 550 551 void 552 do_create_partition(partition_map_header *map, int get_type) 553 { 554 long base; 555 long length; 556 char *name = 0; 557 char *type_name = 0; 558 559 if (map == NULL) { 560 bad_input("No partition map exists"); 561 return; 562 } 563 if (!rflag && map->writable == 0) { 564 printf("The map is not writable.\n"); 565 } 566 // XXX add help feature (i.e. '?' in any argument routine prints help string) 567 if (get_base_argument(&base, map) == 0) { 568 return; 569 } 570 if (get_size_argument(&length, map) == 0) { 571 return; 572 } 573 574 if (get_string_argument("Name of partition: ", &name, 1) == 0) { 575 bad_input("Bad name"); 576 return; 577 } 578 if (get_type == 0) { 579 add_partition_to_map(name, kUnixType, base, length, map); 580 } else if (get_string_argument("Type of partition: ", &type_name, 1) == 0) { 581 bad_input("Bad type"); 582 goto xit1; 583 } else { 584 if (istrncmp(type_name, kFreeType, DPISTRLEN) == 0) { 585 bad_input("Can't create a partition with the Free type"); 586 goto xit2; 587 } 588 if (istrncmp(type_name, kMapType, DPISTRLEN) == 0) { 589 bad_input("Can't create a partition with the Map type"); 590 goto xit2; 591 } 592 add_partition_to_map(name, type_name, base, length, map); 593 } 594 #ifdef __m68k__ 595 do_update_dpme(find_entry_by_base(base,map)); 596 #endif 597 xit2: 598 if (type_name) 599 free(type_name); 600 xit1: 601 if (name) 602 free(name); 603 return; 604 } 605 606 607 int 608 get_base_argument(long *number, partition_map_header *map) 609 { 610 partition_map * entry; 611 int result = 0; 612 613 if (get_number_argument("First block: ", number, kDefault) == 0) { 614 bad_input("Bad block number"); 615 } else { 616 result = 1; 617 if (get_partition_modifier()) { 618 entry = find_entry_by_disk_address(*number, map); 619 if (entry == NULL) { 620 bad_input("Bad partition number"); 621 result = 0; 622 } else { 623 *number = entry->data->dpme_pblock_start; 624 } 625 } 626 } 627 return result; 628 } 629 630 631 int 632 get_size_argument(long *number, partition_map_header *map) 633 { 634 partition_map * entry; 635 int result = 0; 636 unsigned long multiple; 637 638 if (get_number_argument("Length in blocks: ", number, kDefault) == 0) { 639 bad_input("Bad length"); 640 } else { 641 multiple = get_multiplier(map->logical_block); 642 if (multiple == 0) { 643 bad_input("Bad multiplier"); 644 } else if (multiple != 1) { 645 *number *= multiple; 646 result = 1; 647 } else if (get_partition_modifier()) { 648 entry = find_entry_by_disk_address(*number, map); 649 if (entry == NULL) { 650 bad_input("Bad partition number"); 651 } else { 652 *number = entry->data->dpme_pblocks; 653 result = 1; 654 } 655 } else { 656 result = 1; 657 } 658 } 659 return result; 660 } 661 662 663 void 664 do_rename_partition(partition_map_header *map) 665 { 666 partition_map * entry; 667 long ix; 668 char *name; 669 670 if (map == NULL) { 671 bad_input("No partition map exists"); 672 return; 673 } 674 if (!rflag && map->writable == 0) { 675 printf("The map is not writable.\n"); 676 } 677 if (get_number_argument("Partition number: ", &ix, kDefault) == 0) { 678 bad_input("Bad partition number"); 679 return; 680 } 681 if (get_string_argument("New name of partition: ", &name, 1) == 0) { 682 bad_input("Bad name"); 683 return; 684 } 685 686 // find partition and change it 687 entry = find_entry_by_disk_address(ix, map); 688 if (entry == NULL) { 689 printf("No such partition\n"); 690 } else { 691 // stuff name into partition map entry data 692 strncpy(entry->data->dpme_name, name, DPISTRLEN); 693 map->changed = 1; 694 } 695 free(name); 696 return; 697 } 698 699 void 700 do_change_type(partition_map_header *map) 701 { 702 partition_map * entry; 703 long ix; 704 char *type = NULL; 705 706 if (map == NULL) { 707 bad_input("No partition map exists"); 708 return; 709 } 710 711 if (!rflag && map->writable == 0) { 712 printf("The map is not writable.\n"); 713 } 714 715 if (get_number_argument("Partition number: ", &ix, kDefault) == 0) { 716 bad_input("Bad partition number"); 717 return; 718 } 719 720 entry = find_entry_by_disk_address(ix, map); 721 722 if (entry == NULL ) { 723 printf("No such partition\n"); 724 goto out; 725 } 726 727 printf("Existing partition type ``%s''.\n", entry->data->dpme_type); 728 if (get_string_argument("New type of partition: ", &type, 1) == 0) { 729 bad_input("Bad type"); 730 goto out; 731 } 732 733 strncpy(entry->data->dpme_type, type, DPISTRLEN); 734 #ifdef __m68k__ 735 do_update_dpme(entry); 736 #endif 737 map->changed = 1; 738 739 out: 740 if (type) 741 free(type); 742 return; 743 } 744 745 746 void 747 do_delete_partition(partition_map_header *map) 748 { 749 partition_map * cur; 750 long ix; 751 752 if (map == NULL) { 753 bad_input("No partition map exists"); 754 return; 755 } 756 if (!rflag && map->writable == 0) { 757 printf("The map is not writable.\n"); 758 } 759 if (get_number_argument("Partition number: ", &ix, kDefault) == 0) { 760 bad_input("Bad partition number"); 761 return; 762 } 763 764 // find partition and delete it 765 cur = find_entry_by_disk_address(ix, map); 766 if (cur == NULL) { 767 printf("No such partition\n"); 768 } else { 769 delete_partition_from_map(cur); 770 } 771 } 772 773 774 void 775 do_reorder(partition_map_header *map) 776 { 777 long old_index; 778 long ix; 779 780 if (map == NULL) { 781 bad_input("No partition map exists"); 782 return; 783 } 784 if (!rflag && map->writable == 0) { 785 printf("The map is not writable.\n"); 786 } 787 if (get_number_argument("Partition number: ", &old_index, kDefault) == 0) { 788 bad_input("Bad partition number"); 789 return; 790 } 791 if (get_number_argument("New number: ", &ix, kDefault) == 0) { 792 bad_input("Bad partition number"); 793 return; 794 } 795 796 move_entry_in_map(old_index, ix, map); 797 } 798 799 800 void 801 do_write_partition_map(partition_map_header *map) 802 { 803 if (map == NULL) { 804 bad_input("No partition map exists"); 805 return; 806 } 807 if (map->changed == 0 && map->written == 0) { 808 bad_input("The map has not been changed."); 809 return; 810 } 811 if (map->writable == 0) { 812 bad_input("The map is not writable."); 813 return; 814 } 815 printf("Writing the map destroys what was there before. "); 816 if (get_okay("Is that okay? [n/y]: ", 0) != 1) { 817 return; 818 } 819 820 write_partition_map(map); 821 822 map->changed = 0; 823 map->written = 1; 824 825 // exit(0); 826 } 827 828 829 void 830 print_expert_notes() 831 { 832 printf("Notes:\n"); 833 printf(" The expert commands are for low level and experimental features.\n"); 834 printf(" These commands are available only when debug mode is on.\n"); 835 printf("\n"); 836 } 837 838 839 int 840 do_expert(partition_map_header *map, char *name) 841 { 842 int command; 843 int quit = 0; 844 845 while (get_command("Expert command (? for help): ", first_get, &command)) { 846 first_get = 0; 847 848 switch (command) { 849 case '?': 850 print_expert_notes(); 851 // fall through 852 case 'H': 853 case 'h': 854 printf("Commands are:\n"); 855 printf(" h print help\n"); 856 printf(" d dump block n\n"); 857 printf(" p print the partition table\n"); 858 if (dflag) { 859 printf(" P (show data structures - debugging)\n"); 860 } 861 printf(" f full display of nth entry\n"); 862 printf(" v validate map\n"); 863 printf(" e examine patch partition\n"); 864 printf(" q return to main edit menu\n"); 865 printf(" Q quit editing\n"); 866 break; 867 case 'q': 868 flush_to_newline(1); 869 goto finis; 870 break; 871 case 'Q': 872 if (map->changed) { 873 if (get_okay("Discard changes? [n/y]: ", 0) != 1) { 874 break; 875 } 876 } 877 quit = 1; 878 goto finis; 879 break; 880 case 'P': 881 if (dflag) { 882 show_data_structures(map); 883 break; 884 } 885 // fall through 886 case 'p': 887 dump_partition_map(map, 1); 888 break; 889 case 'D': 890 case 'd': 891 do_display_block(map, name); 892 break; 893 case 'F': 894 case 'f': 895 do_display_entry(map); 896 break; 897 case 'V': 898 case 'v': 899 validate_map(map); 900 break; 901 case 'E': 902 case 'e': 903 do_examine_patch_partition(map); 904 break; 905 default: 906 bad_input("No such command (%c)", command); 907 break; 908 } 909 } 910 finis: 911 return quit; 912 } 913 914 void 915 do_change_map_size(partition_map_header *map) 916 { 917 long size; 918 919 if (map == NULL) { 920 bad_input("No partition map exists"); 921 return; 922 } 923 if (!rflag && map->writable == 0) { 924 printf("The map is not writable.\n"); 925 } 926 if (get_number_argument("New size: ", &size, kDefault) == 0) { 927 bad_input("Bad size"); 928 return; 929 } 930 resize_map(size, map); 931 } 932 933 934 void 935 do_display_block(partition_map_header *map, char *alt_name) 936 { 937 MEDIA m; 938 long number; 939 char *name; 940 static unsigned char *display_block; 941 static int display_g; 942 int g; 943 static long next_number = -1; 944 945 if (map != NULL) { 946 name = 0; 947 m = map->m; 948 g = map->logical_block; 949 } else { 950 if (alt_name == 0) { 951 if (get_string_argument("Name of device: ", &name, 1) == 0) { 952 bad_input("Bad name"); 953 return; 954 } 955 } else { 956 if ((name = strdup(alt_name)) == NULL) { 957 error(errno, "strdup failed"); 958 return; 959 } 960 } 961 m = open_pathname_as_media(name, O_RDONLY); 962 if (m == 0) { 963 error(errno, "can't open file '%s'", name); 964 free(name); 965 return; 966 } 967 g = media_granularity(m); 968 if (g < PBLOCK_SIZE) { 969 g = PBLOCK_SIZE; 970 } 971 } 972 if (get_number_argument("Block number: ", &number, next_number) == 0) { 973 bad_input("Bad block number"); 974 goto xit; 975 } 976 if (display_block == NULL || display_g < g) { 977 if (display_block != NULL) { 978 free(display_block); 979 display_g = 0; 980 } 981 display_block = (unsigned char *) malloc(g); 982 if (display_block == NULL) { 983 error(errno, "can't allocate memory for display block buffer"); 984 goto xit; 985 } 986 display_g = g; 987 } 988 if (read_media(m, ((long long)number) * g, g, (char *)display_block) != 0) { 989 printf("block %ld -", number); 990 dump_block((unsigned char*) display_block, g); 991 next_number = number + 1; 992 } 993 994 xit: 995 if (name) { 996 close_media(m); 997 free(name); 998 } 999 return; 1000 } 1001 1002 1003 void 1004 do_display_entry(partition_map_header *map) 1005 { 1006 long number; 1007 1008 if (map == NULL) { 1009 bad_input("No partition map exists"); 1010 return; 1011 } 1012 if (get_number_argument("Partition number: ", &number, kDefault) == 0) { 1013 bad_input("Bad partition number"); 1014 return; 1015 } 1016 if (number == 0) { 1017 full_dump_block_zero(map); 1018 } else { 1019 full_dump_partition_entry(map, number); 1020 } 1021 } 1022 1023 1024 void 1025 do_examine_patch_partition(partition_map_header *map) 1026 { 1027 partition_map * entry; 1028 1029 if (map == NULL) { 1030 bad_input("No partition map exists"); 1031 return; 1032 } 1033 entry = find_entry_by_type(kPatchType, map); 1034 if (entry == NULL) { 1035 printf("No patch partition\n"); 1036 } else { 1037 display_patches(entry); 1038 } 1039 } 1040