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 usage("no device argument"); 176 do_help(); 177 } 178 } else if (name_index < argc) { 179 while (name_index < argc) { 180 edit(argv[name_index++], 0); 181 } 182 } else if (!vflag) { 183 usage("no device argument"); 184 do_help(); 185 } 186 return 0; 187 } 188 189 190 void 191 interact() 192 { 193 char *name; 194 int command; 195 int ask_logical_size; 196 197 while (get_command("Top level command (? for help): ", first_get, &command)) { 198 first_get = 0; 199 ask_logical_size = 0; 200 201 switch (command) { 202 case '?': 203 // fall through 204 case 'H': 205 case 'h': 206 printf("Commands are:\n"); 207 printf(" h print help\n"); 208 printf(" v print the version number and release date\n"); 209 printf(" l list device's map\n"); 210 printf(" e edit device's map\n"); 211 printf(" E (edit map with specified block size)\n"); 212 printf(" r toggle readonly flag\n"); 213 printf(" f toggle show filesystem name flag\n"); 214 if (dflag) { 215 printf(" a toggle abbreviate flag\n"); 216 printf(" p toggle physical flag\n"); 217 printf(" c toggle compute size flag\n"); 218 printf(" d toggle debug flag\n"); 219 printf(" x examine block n of device\n"); 220 } 221 printf(" q quit the program\n"); 222 break; 223 case 'Q': 224 case 'q': 225 return; 226 break; 227 case 'V': 228 case 'v': 229 printf("version " VERSION " (" RELEASE_DATE ")\n"); 230 break; 231 case 'l': 232 if (get_string_argument("Name of device: ", &name, 1) == 0) { 233 bad_input("Bad name"); 234 break; 235 } 236 dump(name); 237 free(name); 238 break; 239 case 'E': 240 ask_logical_size = 1; 241 case 'e': 242 if (get_string_argument("Name of device: ", &name, 1) == 0) { 243 bad_input("Bad name"); 244 break; 245 } 246 edit(name, ask_logical_size); 247 free(name); 248 break; 249 case 'R': 250 case 'r': 251 if (rflag) { 252 rflag = 0; 253 } else { 254 rflag = 1; 255 } 256 printf("Now in %s mode.\n", (rflag)?"readonly":"read/write"); 257 break; 258 case 'F': 259 case 'f': 260 if (fflag) { 261 fflag = 0; 262 } else { 263 fflag = 1; 264 } 265 printf("Now in show %s name mode.\n", (fflag)?"filesystem":"partition"); 266 break; 267 case 'A': 268 case 'a': 269 if (dflag) { 270 if (aflag) { 271 aflag = 0; 272 } else { 273 aflag = 1; 274 } 275 printf("Now in %s mode.\n", (aflag)?"abbreviate":"full type"); 276 } else { 277 goto do_error; 278 } 279 break; 280 case 'P': 281 case 'p': 282 if (dflag) { 283 if (pflag) { 284 pflag = 0; 285 } else { 286 pflag = 1; 287 } 288 printf("Now in %s mode.\n", (pflag)?"physical":"logical"); 289 } else { 290 goto do_error; 291 } 292 break; 293 case 'D': 294 case 'd': 295 if (dflag) { 296 dflag = 0; 297 } else { 298 dflag = 1; 299 } 300 printf("Now in %s mode.\n", (dflag)?"debug":"normal"); 301 break; 302 case 'C': 303 case 'c': 304 if (dflag) { 305 if (cflag) { 306 cflag = 0; 307 } else { 308 cflag = 1; 309 } 310 printf("Now in %s device size mode.\n", (cflag)?"always compute":"use existing"); 311 } else { 312 goto do_error; 313 } 314 break; 315 case 'X': 316 case 'x': 317 if (dflag) { 318 do_display_block(0, 0); 319 } else { 320 goto do_error; 321 } 322 break; 323 default: 324 do_error: 325 bad_input("No such command (%c)", command); 326 break; 327 } 328 } 329 } 330 331 332 int 333 get_options(int argc, char **argv) 334 { 335 int c; 336 extern int optind; 337 extern char *optarg; 338 int flag = 0; 339 340 lflag = LFLAG_DEFAULT; 341 lfile = NULL; 342 vflag = VFLAG_DEFAULT; 343 hflag = HFLAG_DEFAULT; 344 dflag = DFLAG_DEFAULT; 345 rflag = RFLAG_DEFAULT; 346 aflag = AFLAG_DEFAULT; 347 pflag = PFLAG_DEFAULT; 348 interactive = INTERACT_DEFAULT; 349 cflag = CFLAG_DEFAULT; 350 351 optind = 1; // reset option scanner logic 352 while ((c = getopt(argc, argv, "hlvdric")) != -1) { 353 switch (c) { 354 case 'h': 355 hflag = (HFLAG_DEFAULT)?0:1; 356 break; 357 case 'l': 358 lflag = (LFLAG_DEFAULT)?0:1; 359 break; 360 case 'v': 361 vflag = (VFLAG_DEFAULT)?0:1; 362 break; 363 case 'd': 364 dflag = (DFLAG_DEFAULT)?0:1; 365 break; 366 case 'c': 367 cflag = (CFLAG_DEFAULT)?0:1; 368 break; 369 case 'r': 370 rflag = (RFLAG_DEFAULT)?0:1; 371 break; 372 case 'i': 373 interactive = (INTERACT_DEFAULT)?0:1; 374 break; 375 case 'a': 376 aflag = (AFLAG_DEFAULT)?0:1; 377 break; 378 case kLogicalOption: 379 pflag = (PFLAG_DEFAULT)?0:1; 380 break; 381 default: 382 flag = 1; 383 break; 384 } 385 } 386 if (flag) { 387 usage("bad arguments"); 388 } 389 return optind; 390 } 391 392 393 void 394 print_edit_notes() 395 { 396 printf("Notes:\n"); 397 printf(" Base and length fields are blocks, which vary in size between media.\n"); 398 printf(" The base field can be <nth>p; i.e. use the base of the nth partition.\n"); 399 printf(" The length field can be a length followed by k, m, g or t to indicate\n"); 400 printf(" kilo, mega, giga, or tera bytes; also the length can be <nth>p; i.e. use\n"); 401 printf(" the length of the nth partition.\n"); 402 printf(" The name of a partition is descriptive text.\n"); 403 printf("\n"); 404 } 405 406 407 // 408 // Edit the file 409 // 410 void 411 edit(char *name, int ask_logical_size) 412 { 413 partition_map_header *map; 414 int command; 415 int order; 416 int get_type; 417 int valid_file; 418 419 map = open_partition_map(name, &valid_file, ask_logical_size); 420 if (!valid_file) { 421 return; 422 } 423 424 printf("Edit %s -\n", name); 425 426 while (get_command("Command (? for help): ", first_get, &command)) { 427 first_get = 0; 428 order = 1; 429 get_type = 0; 430 431 switch (command) { 432 case '?': 433 print_edit_notes(); 434 // fall through 435 case 'H': 436 case 'h': 437 printf("Commands are:\n"); 438 printf(" C (create with type also specified)\n"); 439 printf(" c create new partition (standard OpenBSD root)\n"); 440 printf(" d delete a partition\n"); 441 printf(" h help\n"); 442 printf(" i initialize partition map\n"); 443 printf(" n (re)name a partition\n"); 444 printf(" P (print ordered by base address)\n"); 445 printf(" p print the partition table\n"); 446 printf(" q quit editing\n"); 447 printf(" r reorder partition entry in map\n"); 448 printf(" s change size of partition map\n"); 449 printf(" t change a partition's type\n"); 450 if (!rflag) { 451 printf(" w write the partition table\n"); 452 } 453 if (dflag) { 454 printf(" x extra extensions for experts\n"); 455 } 456 break; 457 case 'P': 458 order = 0; 459 // fall through 460 case 'p': 461 dump_partition_map(map, order); 462 break; 463 case 'Q': 464 case 'q': 465 if (map && map->changed) { 466 if (get_okay("Discard changes? [n/y]: ", 0) != 1) { 467 break; 468 } 469 } 470 flush_to_newline(1); 471 goto finis; 472 break; 473 case 'I': 474 case 'i': 475 map = init_partition_map(name, map); 476 break; 477 case 'C': 478 get_type = 1; 479 // fall through 480 case 'c': 481 do_create_partition(map, get_type); 482 break; 483 case 'N': 484 case 'n': 485 do_rename_partition(map); 486 break; 487 case 'D': 488 case 'd': 489 do_delete_partition(map); 490 break; 491 case 'R': 492 case 'r': 493 do_reorder(map); 494 break; 495 case 'S': 496 case 's': 497 do_change_map_size(map); 498 break; 499 case 'T': 500 case 't': 501 do_change_type(map); 502 break; 503 case 'X': 504 case 'x': 505 if (!dflag) { 506 goto do_error; 507 } else if (do_expert(map, name)) { 508 flush_to_newline(1); 509 goto finis; 510 } 511 break; 512 case 'W': 513 case 'w': 514 if (!rflag) { 515 do_write_partition_map(map); 516 } else { 517 goto do_error; 518 } 519 break; 520 default: 521 do_error: 522 bad_input("No such command (%c)", command); 523 break; 524 } 525 } 526 finis: 527 528 close_partition_map(map); 529 } 530 531 #ifdef __m68k__ 532 void 533 do_update_dpme(partition_map *entry) 534 { 535 int slice = 0; 536 if (!entry) return; 537 dpme_init_flags(entry->data); 538 entry->HFS_name = get_HFS_name(entry, &entry->HFS_kind); 539 if (istrncmp(entry->data->dpme_type, kUnixType, DPISTRLEN) == 0) { 540 printf("Available partition slices for %s:\n",entry->data->dpme_type); 541 printf(" a root partition\n"); 542 printf(" b swap partition\n"); 543 printf(" c do not set any bzb bits\n"); 544 printf(" g user partition\n"); 545 printf("Other lettered values will create user partitions\n"); 546 get_command("Select a slice for default bzb values: ",0,&slice); 547 } 548 bzb_init_slice((BZB *)entry->data->dpme_bzb,slice); 549 entry->the_map->changed = 1; 550 } 551 #endif 552 553 void 554 do_create_partition(partition_map_header *map, int get_type) 555 { 556 long base; 557 long length; 558 char *name = 0; 559 char *type_name = 0; 560 561 if (map == NULL) { 562 bad_input("No partition map exists"); 563 return; 564 } 565 if (!rflag && map->writable == 0) { 566 printf("The map is not writable.\n"); 567 } 568 // XXX add help feature (i.e. '?' in any argument routine prints help string) 569 if (get_base_argument(&base, map) == 0) { 570 return; 571 } 572 if (get_size_argument(&length, map) == 0) { 573 return; 574 } 575 576 if (get_string_argument("Name of partition: ", &name, 1) == 0) { 577 bad_input("Bad name"); 578 return; 579 } 580 if (get_type == 0) { 581 add_partition_to_map(name, kUnixType, base, length, map); 582 } else if (get_string_argument("Type of partition: ", &type_name, 1) == 0) { 583 bad_input("Bad type"); 584 goto xit1; 585 } else { 586 if (istrncmp(type_name, kFreeType, DPISTRLEN) == 0) { 587 bad_input("Can't create a partition with the Free type"); 588 goto xit2; 589 } 590 if (istrncmp(type_name, kMapType, DPISTRLEN) == 0) { 591 bad_input("Can't create a partition with the Map type"); 592 goto xit2; 593 } 594 add_partition_to_map(name, type_name, base, length, map); 595 } 596 #ifdef __m68k__ 597 do_update_dpme(find_entry_by_base(base,map)); 598 #endif 599 xit2: 600 if (type_name) 601 free(type_name); 602 xit1: 603 if (name) 604 free(name); 605 return; 606 } 607 608 609 int 610 get_base_argument(long *number, partition_map_header *map) 611 { 612 partition_map * entry; 613 int result = 0; 614 615 if (get_number_argument("First block: ", number, kDefault) == 0) { 616 bad_input("Bad block number"); 617 } else { 618 result = 1; 619 if (get_partition_modifier()) { 620 entry = find_entry_by_disk_address(*number, map); 621 if (entry == NULL) { 622 bad_input("Bad partition number"); 623 result = 0; 624 } else { 625 *number = entry->data->dpme_pblock_start; 626 } 627 } 628 } 629 return result; 630 } 631 632 633 int 634 get_size_argument(long *number, partition_map_header *map) 635 { 636 partition_map * entry; 637 int result = 0; 638 unsigned long multiple; 639 640 if (get_number_argument("Length in blocks: ", number, kDefault) == 0) { 641 bad_input("Bad length"); 642 } else { 643 multiple = get_multiplier(map->logical_block); 644 if (multiple == 0) { 645 bad_input("Bad multiplier"); 646 } else if (multiple != 1) { 647 *number *= multiple; 648 result = 1; 649 } else if (get_partition_modifier()) { 650 entry = find_entry_by_disk_address(*number, map); 651 if (entry == NULL) { 652 bad_input("Bad partition number"); 653 } else { 654 *number = entry->data->dpme_pblocks; 655 result = 1; 656 } 657 } else { 658 result = 1; 659 } 660 } 661 return result; 662 } 663 664 665 void 666 do_rename_partition(partition_map_header *map) 667 { 668 partition_map * entry; 669 long ix; 670 char *name; 671 672 if (map == NULL) { 673 bad_input("No partition map exists"); 674 return; 675 } 676 if (!rflag && map->writable == 0) { 677 printf("The map is not writable.\n"); 678 } 679 if (get_number_argument("Partition number: ", &ix, kDefault) == 0) { 680 bad_input("Bad partition number"); 681 return; 682 } 683 if (get_string_argument("New name of partition: ", &name, 1) == 0) { 684 bad_input("Bad name"); 685 return; 686 } 687 688 // find partition and change it 689 entry = find_entry_by_disk_address(ix, map); 690 if (entry == NULL) { 691 printf("No such partition\n"); 692 } else { 693 // stuff name into partition map entry data 694 strncpy(entry->data->dpme_name, name, DPISTRLEN); 695 map->changed = 1; 696 } 697 free(name); 698 return; 699 } 700 701 void 702 do_change_type(partition_map_header *map) 703 { 704 partition_map * entry; 705 long ix; 706 char *type = NULL; 707 708 if (map == NULL) { 709 bad_input("No partition map exists"); 710 return; 711 } 712 713 if (!rflag && map->writable == 0) { 714 printf("The map is not writable.\n"); 715 } 716 717 if (get_number_argument("Partition number: ", &ix, kDefault) == 0) { 718 bad_input("Bad partition number"); 719 return; 720 } 721 722 entry = find_entry_by_disk_address(ix, map); 723 724 if (entry == NULL ) { 725 printf("No such partition\n"); 726 goto out; 727 } 728 729 printf("Existing partition type ``%s''.\n", entry->data->dpme_type); 730 if (get_string_argument("New type of partition: ", &type, 1) == 0) { 731 bad_input("Bad type"); 732 goto out; 733 } 734 735 strncpy(entry->data->dpme_type, type, DPISTRLEN); 736 #ifdef __m68k__ 737 do_update_dpme(entry); 738 #endif 739 map->changed = 1; 740 741 out: 742 if (type) 743 free(type); 744 return; 745 } 746 747 748 void 749 do_delete_partition(partition_map_header *map) 750 { 751 partition_map * cur; 752 long ix; 753 754 if (map == NULL) { 755 bad_input("No partition map exists"); 756 return; 757 } 758 if (!rflag && map->writable == 0) { 759 printf("The map is not writable.\n"); 760 } 761 if (get_number_argument("Partition number: ", &ix, kDefault) == 0) { 762 bad_input("Bad partition number"); 763 return; 764 } 765 766 // find partition and delete it 767 cur = find_entry_by_disk_address(ix, map); 768 if (cur == NULL) { 769 printf("No such partition\n"); 770 } else { 771 delete_partition_from_map(cur); 772 } 773 } 774 775 776 void 777 do_reorder(partition_map_header *map) 778 { 779 long old_index; 780 long ix; 781 782 if (map == NULL) { 783 bad_input("No partition map exists"); 784 return; 785 } 786 if (!rflag && map->writable == 0) { 787 printf("The map is not writable.\n"); 788 } 789 if (get_number_argument("Partition number: ", &old_index, kDefault) == 0) { 790 bad_input("Bad partition number"); 791 return; 792 } 793 if (get_number_argument("New number: ", &ix, kDefault) == 0) { 794 bad_input("Bad partition number"); 795 return; 796 } 797 798 move_entry_in_map(old_index, ix, map); 799 } 800 801 802 void 803 do_write_partition_map(partition_map_header *map) 804 { 805 if (map == NULL) { 806 bad_input("No partition map exists"); 807 return; 808 } 809 if (map->changed == 0 && map->written == 0) { 810 bad_input("The map has not been changed."); 811 return; 812 } 813 if (map->writable == 0) { 814 bad_input("The map is not writable."); 815 return; 816 } 817 printf("Writing the map destroys what was there before. "); 818 if (get_okay("Is that okay? [n/y]: ", 0) != 1) { 819 return; 820 } 821 822 write_partition_map(map); 823 824 map->changed = 0; 825 map->written = 1; 826 827 // exit(0); 828 } 829 830 831 void 832 print_expert_notes() 833 { 834 printf("Notes:\n"); 835 printf(" The expert commands are for low level and experimental features.\n"); 836 printf(" These commands are available only when debug mode is on.\n"); 837 printf("\n"); 838 } 839 840 841 int 842 do_expert(partition_map_header *map, char *name) 843 { 844 int command; 845 int quit = 0; 846 847 while (get_command("Expert command (? for help): ", first_get, &command)) { 848 first_get = 0; 849 850 switch (command) { 851 case '?': 852 print_expert_notes(); 853 // fall through 854 case 'H': 855 case 'h': 856 printf("Commands are:\n"); 857 printf(" h print help\n"); 858 printf(" d dump block n\n"); 859 printf(" p print the partition table\n"); 860 if (dflag) { 861 printf(" P (show data structures - debugging)\n"); 862 } 863 printf(" f full display of nth entry\n"); 864 printf(" v validate map\n"); 865 printf(" e examine patch partition\n"); 866 printf(" q return to main edit menu\n"); 867 printf(" Q quit editing\n"); 868 break; 869 case 'q': 870 flush_to_newline(1); 871 goto finis; 872 break; 873 case 'Q': 874 if (map->changed) { 875 if (get_okay("Discard changes? [n/y]: ", 0) != 1) { 876 break; 877 } 878 } 879 quit = 1; 880 goto finis; 881 break; 882 case 'P': 883 if (dflag) { 884 show_data_structures(map); 885 break; 886 } 887 // fall through 888 case 'p': 889 dump_partition_map(map, 1); 890 break; 891 case 'D': 892 case 'd': 893 do_display_block(map, name); 894 break; 895 case 'F': 896 case 'f': 897 do_display_entry(map); 898 break; 899 case 'V': 900 case 'v': 901 validate_map(map); 902 break; 903 case 'E': 904 case 'e': 905 do_examine_patch_partition(map); 906 break; 907 default: 908 bad_input("No such command (%c)", command); 909 break; 910 } 911 } 912 finis: 913 return quit; 914 } 915 916 void 917 do_change_map_size(partition_map_header *map) 918 { 919 long size; 920 921 if (map == NULL) { 922 bad_input("No partition map exists"); 923 return; 924 } 925 if (!rflag && map->writable == 0) { 926 printf("The map is not writable.\n"); 927 } 928 if (get_number_argument("New size: ", &size, kDefault) == 0) { 929 bad_input("Bad size"); 930 return; 931 } 932 resize_map(size, map); 933 } 934 935 936 void 937 do_display_block(partition_map_header *map, char *alt_name) 938 { 939 MEDIA m; 940 long number; 941 char *name; 942 static unsigned char *display_block; 943 static int display_g; 944 int g; 945 static long next_number = -1; 946 947 if (map != NULL) { 948 name = 0; 949 m = map->m; 950 g = map->logical_block; 951 } else { 952 if (alt_name == 0) { 953 if (get_string_argument("Name of device: ", &name, 1) == 0) { 954 bad_input("Bad name"); 955 return; 956 } 957 } else { 958 if ((name = strdup(alt_name)) == NULL) { 959 error(errno, "strdup failed"); 960 return; 961 } 962 } 963 m = open_pathname_as_media(name, O_RDONLY); 964 if (m == 0) { 965 error(errno, "can't open file '%s'", name); 966 free(name); 967 return; 968 } 969 g = media_granularity(m); 970 if (g < PBLOCK_SIZE) { 971 g = PBLOCK_SIZE; 972 } 973 } 974 if (get_number_argument("Block number: ", &number, next_number) == 0) { 975 bad_input("Bad block number"); 976 goto xit; 977 } 978 if (display_block == NULL || display_g < g) { 979 if (display_block != NULL) { 980 free(display_block); 981 display_g = 0; 982 } 983 display_block = (unsigned char *) malloc(g); 984 if (display_block == NULL) { 985 error(errno, "can't allocate memory for display block buffer"); 986 goto xit; 987 } 988 display_g = g; 989 } 990 if (read_media(m, ((long long)number) * g, g, (char *)display_block) != 0) { 991 printf("block %ld -", number); 992 dump_block((unsigned char*) display_block, g); 993 next_number = number + 1; 994 } 995 996 xit: 997 if (name) { 998 close_media(m); 999 free(name); 1000 } 1001 return; 1002 } 1003 1004 1005 void 1006 do_display_entry(partition_map_header *map) 1007 { 1008 long number; 1009 1010 if (map == NULL) { 1011 bad_input("No partition map exists"); 1012 return; 1013 } 1014 if (get_number_argument("Partition number: ", &number, kDefault) == 0) { 1015 bad_input("Bad partition number"); 1016 return; 1017 } 1018 if (number == 0) { 1019 full_dump_block_zero(map); 1020 } else { 1021 full_dump_partition_entry(map, number); 1022 } 1023 } 1024 1025 1026 void 1027 do_examine_patch_partition(partition_map_header *map) 1028 { 1029 partition_map * entry; 1030 1031 if (map == NULL) { 1032 bad_input("No partition map exists"); 1033 return; 1034 } 1035 entry = find_entry_by_type(kPatchType, map); 1036 if (entry == NULL) { 1037 printf("No patch partition\n"); 1038 } else { 1039 display_patches(entry); 1040 } 1041 } 1042