1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file contains functions that implement the command menu commands. 31 */ 32 33 #include "global.h" 34 #include <time.h> 35 #include <sys/time.h> 36 #include <sys/resource.h> 37 #include <sys/wait.h> 38 #include <strings.h> 39 #include <signal.h> 40 #include <stdlib.h> 41 #include <string.h> 42 43 #if defined(sparc) 44 #include <sys/hdio.h> 45 #endif /* defined(sparc) */ 46 47 #include "main.h" 48 #include "analyze.h" 49 #include "menu.h" 50 #include "menu_command.h" 51 #include "menu_defect.h" 52 #include "menu_partition.h" 53 #include "param.h" 54 #include "misc.h" 55 #include "label.h" 56 #include "startup.h" 57 #include "partition.h" 58 #include "prompts.h" 59 #include "checkmount.h" 60 #include "io.h" 61 #include "ctlr_scsi.h" 62 #include "auto_sense.h" 63 #include "modify_partition.h" 64 65 66 extern struct menu_item menu_partition[]; 67 extern struct menu_item menu_analyze[]; 68 extern struct menu_item menu_defect[]; 69 70 /* 71 * Choices for the p_tag vtoc field 72 */ 73 slist_t ptag_choices[] = { 74 { "unassigned", "", V_UNASSIGNED }, 75 { "boot", "", V_BOOT }, 76 { "root", "", V_ROOT }, 77 { "swap", "", V_SWAP }, 78 { "usr", "", V_USR }, 79 { "backup", "", V_BACKUP }, 80 { "stand", "", V_STAND }, 81 { "var", "", V_VAR }, 82 { "home", "", V_HOME }, 83 { "alternates", "", V_ALTSCTR }, 84 { "reserved", "", V_RESERVED }, 85 { NULL } 86 }; 87 88 89 /* 90 * Choices for the p_flag vtoc field 91 */ 92 slist_t pflag_choices[] = { 93 { "wm", "read-write, mountable", 0 }, 94 { "wu", "read-write, unmountable", V_UNMNT }, 95 { "rm", "read-only, mountable", V_RONLY }, 96 { "ru", "read-only, unmountable", V_RONLY|V_UNMNT }, 97 { NULL } 98 }; 99 100 101 /* 102 * This routine implements the 'disk' command. It allows the user to 103 * select a disk to be current. The list of choices is the list of 104 * disks that were found at startup time. 105 */ 106 int 107 c_disk() 108 { 109 struct disk_info *disk; 110 u_ioparam_t ioparam; 111 int i; 112 int ndisks = 0; 113 int blind_select = 0; 114 int deflt; 115 int index; 116 int *defltptr = NULL; 117 int more = 0; 118 int more_quit = 0; 119 int one_line = 0; 120 int tty_lines; 121 122 /* 123 * This buffer holds the check() prompt that verifies we've got the right 124 * disk when performing a blind selection. The size should be sufficient 125 * to hold the prompt string, plus 256 characters for the disk name - 126 * way more than should ever be necessary. See the #define in misc.h. 127 */ 128 char chk_buf[BLIND_SELECT_VER_PROMPT]; 129 130 if (istokenpresent()) { 131 /* 132 * disk number to be selected is already in the 133 * input stream . 134 */ 135 TOKEN token, cleantoken; 136 137 /* 138 * Get the disk number the user has given. 139 */ 140 i = 0; 141 for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 142 i++; 143 } 144 145 ioparam.io_bounds.lower = 0; 146 ioparam.io_bounds.upper = i - 1; 147 (void) gettoken(token); 148 clean_token(cleantoken, token); 149 150 /* 151 * Convert the token into an integer. 152 */ 153 if (geti(cleantoken, (int *)&index, (int *)NULL)) 154 return (0); 155 156 /* 157 * Check to be sure it is within the legal bounds. 158 */ 159 if ((index < 0) || (index >= i)) { 160 err_print("`%d' is out of range.\n", index); 161 return (0); 162 } 163 goto checkdisk; 164 } 165 166 fmt_print("\n\nAVAILABLE DISK SELECTIONS:\n"); 167 168 i = 0; 169 if ((option_f == (char *)NULL) && isatty(0) == 1 && isatty(1) == 1) { 170 /* 171 * We have a real terminal for std input and output, enable 172 * more style of output for disk selection list. 173 */ 174 more = 1; 175 tty_lines = get_tty_lines(); 176 enter_critical(); 177 echo_off(); 178 charmode_on(); 179 exit_critical(); 180 } 181 182 /* 183 * Loop through the list of found disks. 184 */ 185 for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 186 /* 187 * If using more output, account 2 lines for each disk. 188 */ 189 if (more && !more_quit && i && (one_line || 190 ((2 * i + 1) % (tty_lines - 2) <= 1))) { 191 int c; 192 193 /* 194 * Get the next character. 195 */ 196 fmt_print("- hit space for more or s to select - "); 197 c = getchar(); 198 fmt_print("\015"); 199 one_line = 0; 200 /* 201 * Handle display one line command 202 * (return key) 203 */ 204 if (c == '\012') { 205 one_line++; 206 } 207 /* Handle Quit command */ 208 if (c == 'q') { 209 fmt_print( 210 " \015"); 211 more_quit++; 212 } 213 /* Handle ^D command */ 214 if (c == '\004') 215 fullabort(); 216 /* or get on with the show */ 217 if (c == 's' || c == 'S') { 218 fmt_print("%80s\n", " "); 219 break; 220 } 221 } 222 /* 223 * If this is the current disk, mark it as 224 * the default. 225 */ 226 if (cur_disk == disk) { 227 deflt = i; 228 defltptr = &deflt; 229 } 230 if (!more || !more_quit) 231 pr_diskline(disk, i); 232 i++; 233 } 234 if (more) { 235 enter_critical(); 236 charmode_off(); 237 echo_on(); 238 exit_critical(); 239 } 240 241 /* 242 * Determine total number of disks, and ask the user which disk he 243 * would like to make current. 244 */ 245 246 for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 247 ndisks++; 248 } 249 250 ioparam.io_bounds.lower = 0; 251 ioparam.io_bounds.upper = ndisks - 1; 252 index = input(FIO_INT, "Specify disk (enter its number)", ':', 253 &ioparam, defltptr, DATA_INPUT); 254 255 if (index >= i) { 256 blind_select = 1; 257 } 258 259 /* 260 * Find the disk chosen. Search through controllers/disks 261 * in the same original order, so we match what the user 262 * chose. 263 */ 264 checkdisk: 265 i = 0; 266 for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 267 if (i == index) 268 goto found; 269 i++; 270 } 271 /* 272 * Should never happen. 273 */ 274 impossible("no disk found"); 275 276 found: 277 if (blind_select) { 278 (void) snprintf(chk_buf, sizeof (chk_buf), 279 "Disk %s selected - is this the desired disk? ", disk->disk_name); 280 if (check(chk_buf)) { 281 return (-1); 282 } 283 } 284 285 /* 286 * Update the state. We lock out interrupts so the state can't 287 * get half-updated. 288 */ 289 290 enter_critical(); 291 init_globals(disk); 292 exit_critical(); 293 294 /* 295 * If type unknown and interactive, ask user to specify type. 296 * Also, set partition table (best guess) too. 297 */ 298 if (!option_f && ncyl == 0 && nhead == 0 && nsect == 0 && 299 (disk->label_type != L_TYPE_EFI)) { 300 (void) c_type(); 301 } 302 303 /* 304 * Get the Solaris Fdisk Partition information 305 */ 306 if (nhead != 0 && nsect != 0) 307 (void) copy_solaris_part(&cur_disk->fdisk_part); 308 309 if ((cur_disk->label_type == L_TYPE_EFI) && 310 (cur_disk->disk_parts->etoc->efi_flags & 311 EFI_GPT_PRIMARY_CORRUPT)) { 312 err_print("Reading the primary EFI GPT label "); 313 err_print("failed. Using backup label.\n"); 314 err_print("Use the 'backup' command to restore "); 315 err_print("the primary label.\n"); 316 } 317 /* 318 * If the label of the disk is marked dirty, 319 * see if they'd like to label the disk now. 320 */ 321 if (cur_disk->disk_flags & DSK_LABEL_DIRTY) { 322 if (check("Disk not labeled. Label it now") == 0) { 323 if (write_label()) { 324 err_print("Write label failed\n"); 325 } else { 326 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 327 } 328 } 329 } 330 return (0); 331 } 332 333 /* 334 * This routine implements the 'type' command. It allows the user to 335 * specify the type of the current disk. It should be necessary only 336 * if the disk was not labelled or was somehow labelled incorrectly. 337 * The list of legal types for the disk comes from information that was 338 * in the data file. 339 */ 340 int 341 c_type() 342 { 343 struct disk_type *type, *tptr, *oldtype; 344 u_ioparam_t ioparam; 345 int i, index, deflt, *defltptr = NULL; 346 struct disk_type disk_type; 347 struct disk_type *d = &disk_type; 348 int first_disk; 349 int auto_conf_choice; 350 int other_choice; 351 struct dk_label label; 352 struct efi_info efi_info; 353 uint64_t maxLBA; 354 char volname[LEN_DKL_VVOL]; 355 int volinit = 0; 356 357 /* 358 * There must be a current disk. 359 */ 360 if (cur_disk == NULL) { 361 err_print("Current Disk is not set.\n"); 362 return (-1); 363 } 364 oldtype = cur_disk->disk_type; 365 type = cur_ctype->ctype_dlist; 366 /* 367 * Print out the list of choices. 368 */ 369 fmt_print("\n\nAVAILABLE DRIVE TYPES:\n"); 370 first_disk = 0; 371 if (cur_ctype->ctype_ctype == DKC_SCSI_CCS) { 372 auto_conf_choice = 0; 373 fmt_print(" %d. Auto configure\n", first_disk++); 374 } else { 375 auto_conf_choice = -1; 376 } 377 i = first_disk; 378 for (tptr = type; tptr != NULL; tptr = tptr->dtype_next) { 379 /* 380 * If we pass the current type, mark it to be the default. 381 */ 382 if (cur_dtype == tptr) { 383 deflt = i; 384 defltptr = &deflt; 385 } 386 if (cur_disk->label_type == L_TYPE_EFI) { 387 continue; 388 } 389 if (tptr->dtype_asciilabel) 390 fmt_print(" %d. %s\n", i++, tptr->dtype_asciilabel); 391 } 392 other_choice = i; 393 fmt_print(" %d. other\n", i); 394 ioparam.io_bounds.lower = 0; 395 ioparam.io_bounds.upper = i; 396 /* 397 * Ask the user which type the disk is. 398 */ 399 index = input(FIO_INT, "Specify disk type (enter its number)", ':', 400 &ioparam, defltptr, DATA_INPUT); 401 /* 402 * Find the type s/he chose. 403 */ 404 if (index == auto_conf_choice) { 405 float scaled; 406 long nblks; 407 int nparts; 408 409 /* 410 * User chose "auto configure". 411 */ 412 (void) strcpy(x86_devname, cur_disk->disk_name); 413 switch (cur_disk->label_type) { 414 case L_TYPE_SOLARIS: 415 if ((tptr = auto_sense(cur_file, 1, &label)) == NULL) { 416 err_print("Auto configure failed\n"); 417 return (-1); 418 } 419 fmt_print("%s: configured with capacity of ", 420 cur_disk->disk_name); 421 nblks = tptr->dtype_ncyl * tptr->dtype_nhead * 422 tptr->dtype_nsect; 423 scaled = bn2mb(nblks); 424 if (scaled > 1024.0) { 425 fmt_print("%1.2fGB\n", scaled/1024.0); 426 } else { 427 fmt_print("%1.2fMB\n", scaled); 428 } 429 fmt_print("<%s cyl %d alt %d hd %d sec %d>\n", 430 tptr->dtype_asciilabel, tptr->dtype_ncyl, 431 tptr->dtype_acyl, tptr->dtype_nhead, 432 tptr->dtype_nsect); 433 break; 434 case L_TYPE_EFI: 435 if ((tptr = auto_efi_sense(cur_file, &efi_info)) == NULL) { 436 err_print("Auto configure failed\n"); 437 return (-1); 438 } 439 fmt_print("%s: configured with capacity of ", 440 cur_disk->disk_name); 441 scaled = bn2mb(efi_info.capacity); 442 if (scaled > 1024.0) { 443 fmt_print("%1.2fGB\n", scaled/1024.0); 444 } else { 445 fmt_print("%1.2fMB\n", scaled); 446 } 447 print_efi_string(efi_info.vendor, efi_info.product, 448 efi_info.revision, efi_info.capacity); 449 fmt_print("\n"); 450 for (nparts = 0; nparts < cur_parts->etoc->efi_nparts; 451 nparts++) { 452 if (cur_parts->etoc->efi_parts[nparts].p_tag == 453 V_RESERVED) { 454 if (cur_parts->etoc->efi_parts[nparts].p_name) { 455 (void) strcpy(volname, 456 cur_parts->etoc->efi_parts[nparts].p_name); 457 volinit = 1; 458 } 459 break; 460 } 461 } 462 enter_critical(); 463 free(cur_disk->disk_type); 464 cur_disk->disk_type = tptr; 465 cur_disk->disk_parts = tptr->dtype_plist; 466 init_globals(cur_disk); 467 exit_critical(); 468 if (volinit) { 469 for (nparts = 0; nparts < cur_parts->etoc->efi_nparts; 470 nparts++) { 471 if (cur_parts->etoc->efi_parts[nparts].p_tag == 472 V_RESERVED) { 473 (void) strcpy( 474 cur_parts->etoc->efi_parts[nparts].p_name, 475 volname); 476 (void) strlcpy(cur_disk->v_volume, volname, 477 LEN_DKL_VVOL); 478 break; 479 } 480 } 481 } 482 return (0); 483 break; 484 default: 485 /* Should never happen */ 486 return (-1); 487 } 488 } else if ((index == other_choice) && (cur_label == L_TYPE_SOLARIS)) { 489 /* 490 * User chose "other". 491 * Get the standard information on the new type. 492 * Put all information in a tmp structure, in 493 * case user aborts. 494 */ 495 bzero((char *)d, sizeof (struct disk_type)); 496 497 d->dtype_ncyl = get_ncyl(); 498 d->dtype_acyl = get_acyl(d->dtype_ncyl); 499 d->dtype_pcyl = get_pcyl(d->dtype_ncyl, d->dtype_acyl); 500 d->dtype_nhead = get_nhead(); 501 d->dtype_phead = get_phead(d->dtype_nhead, &d->dtype_options); 502 d->dtype_nsect = get_nsect(); 503 d->dtype_psect = get_psect(&d->dtype_options); 504 d->dtype_bpt = get_bpt(d->dtype_nsect, &d->dtype_options); 505 d->dtype_rpm = get_rpm(); 506 d->dtype_fmt_time = get_fmt_time(&d->dtype_options); 507 d->dtype_cyl_skew = get_cyl_skew(&d->dtype_options); 508 d->dtype_trk_skew = get_trk_skew(&d->dtype_options); 509 d->dtype_trks_zone = get_trks_zone(&d->dtype_options); 510 d->dtype_atrks = get_atrks(&d->dtype_options); 511 d->dtype_asect = get_asect(&d->dtype_options); 512 d->dtype_cache = get_cache(&d->dtype_options); 513 d->dtype_threshold = get_threshold(&d->dtype_options); 514 d->dtype_prefetch_min = get_min_prefetch(&d->dtype_options); 515 d->dtype_prefetch_max = get_max_prefetch(d->dtype_prefetch_min, 516 &d->dtype_options); 517 d->dtype_bps = get_bps(); 518 #if defined(sparc) 519 d->dtype_dr_type = 0; 520 #endif /* defined(sparc) */ 521 522 d->dtype_asciilabel = get_asciilabel(); 523 524 /* 525 * Add the new type to the list of possible types for 526 * this controller. We lock out interrupts so the lists 527 * can't get munged. We put off actually allocating the 528 * structure till here in case the user wanted to 529 * interrupt while still inputting information. 530 */ 531 enter_critical(); 532 tptr = (struct disk_type *)zalloc(sizeof (struct disk_type)); 533 if (type == NULL) 534 cur_ctype->ctype_dlist = tptr; 535 else { 536 while (type->dtype_next != NULL) 537 type = type->dtype_next; 538 type->dtype_next = tptr; 539 } 540 bcopy((char *)d, (char *)tptr, sizeof (disk_type)); 541 tptr->dtype_next = NULL; 542 /* 543 * the new disk type does not have any defined 544 * partition table . Hence copy the current partition 545 * table if possible else create a default 546 * paritition table. 547 */ 548 new_partitiontable(tptr, oldtype); 549 } else if ((index == other_choice) && (cur_label == L_TYPE_EFI)) { 550 maxLBA = get_mlba(); 551 cur_parts->etoc->efi_last_lba = maxLBA; 552 cur_parts->etoc->efi_last_u_lba = maxLBA - 34; 553 for (i = 0; i < cur_parts->etoc->efi_nparts; i++) { 554 cur_parts->etoc->efi_parts[i].p_start = 0; 555 cur_parts->etoc->efi_parts[i].p_size = 0; 556 cur_parts->etoc->efi_parts[i].p_tag = V_UNASSIGNED; 557 } 558 cur_parts->etoc->efi_parts[8].p_start = 559 maxLBA - 34 - (1024 * 16); 560 cur_parts->etoc->efi_parts[8].p_size = (1024 * 16); 561 cur_parts->etoc->efi_parts[8].p_tag = V_RESERVED; 562 if (write_label()) { 563 err_print("Write label failed\n"); 564 } else { 565 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 566 } 567 return (0); 568 } else { 569 /* 570 * User picked an existing disk type. 571 */ 572 i = first_disk; 573 tptr = type; 574 while (i < index) { 575 if (tptr->dtype_asciilabel) { 576 i++; 577 } 578 tptr = tptr->dtype_next; 579 } 580 if ((tptr->dtype_asciilabel == NULL) && 581 (tptr->dtype_next != NULL)) { 582 while (tptr->dtype_asciilabel == NULL) { 583 tptr = tptr->dtype_next; 584 } 585 } 586 } 587 /* 588 * Check for mounted file systems in the format zone. 589 * One potential problem with this would be that check() 590 * always returns 'yes' when running out of a file. However, 591 * it is actually ok because we don't let the program get 592 * started if there are mounted file systems and we are 593 * running from a file. 594 */ 595 if ((tptr != oldtype) && 596 checkmount((daddr_t)-1, (daddr_t)-1)) { 597 err_print( 598 "Cannot set disk type while it has mounted partitions.\n\n"); 599 return (-1); 600 } 601 /* 602 * check for partitions being used for swapping in format zone 603 */ 604 if ((tptr != oldtype) && 605 checkswap((daddr_t)-1, (daddr_t)-1)) { 606 err_print("Cannot set disk type while its partition are \ 607 currently being used for swapping.\n"); 608 return (-1); 609 } 610 /* 611 * If the type selected is different from the previous type, 612 * mark the disk as not labelled and reload the current 613 * partition info. This is not essential but probably the 614 * right thing to do, since the size of the disk has probably 615 * changed. 616 */ 617 enter_critical(); 618 if (tptr != oldtype) { 619 cur_disk->disk_type = tptr; 620 cur_disk->disk_parts = NULL; 621 cur_disk->disk_flags &= ~DSK_LABEL; 622 } 623 /* 624 * Initialize the state of the current disk. 625 */ 626 init_globals(cur_disk); 627 (void) get_partition(); 628 exit_critical(); 629 630 /* 631 * If the label of the disk is marked dirty, 632 * see if they'd like to label the disk now. 633 */ 634 if (cur_disk->disk_flags & DSK_LABEL_DIRTY) { 635 if (check("Disk not labeled. Label it now") == 0) { 636 if (write_label()) { 637 err_print("Write label failed\n"); 638 } else { 639 cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; 640 } 641 } 642 } 643 644 return (0); 645 } 646 647 /* 648 * This routine implements the 'partition' command. It simply runs 649 * the partition menu. 650 */ 651 int 652 c_partition() 653 { 654 655 /* 656 * There must be a current disk type and a current disk 657 */ 658 if (cur_dtype == NULL) { 659 err_print("Current Disk Type is not set.\n"); 660 return (-1); 661 } 662 /* 663 * Check for a valid fdisk table entry for Solaris 664 */ 665 if (!good_fdisk()) { 666 err_print("Please run fdisk first.\n"); 667 return (-1); 668 } 669 670 cur_menu++; 671 last_menu = cur_menu; 672 673 #ifdef not 674 /* 675 * If there is no current partition table, make one. This is 676 * so the commands within the menu never have to check for 677 * a non-existent table. 678 */ 679 if (cur_parts == NULL) 680 err_print("making partition.\n"); 681 make_partition(); 682 #endif /* not */ 683 684 /* 685 * Run the menu. 686 */ 687 run_menu(menu_partition, "PARTITION", "partition", 0); 688 cur_menu--; 689 return (0); 690 } 691 692 /* 693 * This routine implements the 'current' command. It describes the 694 * current disk. 695 */ 696 int 697 c_current() 698 { 699 700 /* 701 * If there is no current disk, say so. Note that this is 702 * not an error since it is a legitimate response to the inquiry. 703 */ 704 if (cur_disk == NULL) { 705 fmt_print("No Current Disk.\n"); 706 return (0); 707 } 708 /* 709 * Print out the info we have on the current disk. 710 */ 711 fmt_print("Current Disk = %s", cur_disk->disk_name); 712 if (chk_volname(cur_disk)) { 713 fmt_print(": "); 714 print_volname(cur_disk); 715 } 716 fmt_print("\n"); 717 if (cur_disk->devfs_name != NULL) { 718 if (cur_dtype == NULL) { 719 fmt_print("<type unknown>\n"); 720 } else if (cur_label == L_TYPE_SOLARIS) { 721 fmt_print("<%s cyl %d alt %d hd %d sec %d>\n", 722 cur_dtype->dtype_asciilabel, ncyl, 723 acyl, nhead, nsect); 724 } else if (cur_label == L_TYPE_EFI) { 725 print_efi_string(cur_dtype->vendor, 726 cur_dtype->product, cur_dtype->revision, 727 cur_dtype->capacity); 728 fmt_print("\n"); 729 } 730 fmt_print("%s\n", cur_disk->devfs_name); 731 } else { 732 fmt_print("%s%d: <", cur_ctlr->ctlr_dname, 733 cur_disk->disk_dkinfo.dki_unit); 734 if (cur_dtype == NULL) { 735 fmt_print("type unknown"); 736 } else if (cur_label == L_TYPE_SOLARIS) { 737 fmt_print("%s cyl %d alt %d hd %d sec %d", 738 cur_dtype->dtype_asciilabel, ncyl, 739 acyl, nhead, nsect); 740 } else if (cur_label == L_TYPE_EFI) { 741 print_efi_string(cur_dtype->vendor, 742 cur_dtype->product, cur_dtype->revision, 743 cur_dtype->capacity); 744 fmt_print("\n"); 745 } 746 fmt_print(">\n"); 747 } 748 fmt_print("\n"); 749 return (0); 750 } 751 752 /* 753 * This routine implements the 'format' command. It allows the user 754 * to format and verify any portion of the disk. 755 */ 756 int 757 c_format() 758 { 759 diskaddr_t start, end; 760 time_t clock; 761 int format_time, format_tracks, format_cyls; 762 int format_interval; 763 int deflt, status; 764 u_ioparam_t ioparam; 765 766 /* 767 * There must be a current disk type and a current disk 768 */ 769 if (cur_dtype == NULL) { 770 err_print("Current Disk Type is not set.\n"); 771 return (-1); 772 } 773 774 /* 775 * There must be a format routine in cur_ops structure to have 776 * this routine work. 777 */ 778 if (cur_ops->op_format == NULL) { 779 err_print( 780 "Cannot format this drive. Please use your Manufacturer supplied formatting " 781 "utility.\n"); 782 return (-1); 783 } 784 785 /* 786 * There must be a current defect list. Except for 787 * unformatted SCSI disks. For them the defect list 788 * can only be retrieved after formatting the disk. 789 */ 790 if ((cur_ctype->ctype_flags & CF_SCSI) && !EMBEDDED_SCSI && 791 (cur_ctype->ctype_flags & CF_DEFECTS) && 792 ! (cur_flags & DISK_FORMATTED)) { 793 cur_list.flags |= LIST_RELOAD; 794 795 } else if (cur_list.list == NULL && !EMBEDDED_SCSI) { 796 err_print("Current Defect List must be initialized.\n"); 797 return (-1); 798 } 799 /* 800 * Ask for the bounds of the format. We always use the whole 801 * disk as the default, since that is the most likely case. 802 * Note, for disks which must be formatted accross the whole disk, 803 * don't bother the user. 804 */ 805 ioparam.io_bounds.lower = start = 0; 806 if (cur_label == L_TYPE_SOLARIS) { 807 if (cur_ctype->ctype_flags & CF_SCSI) { 808 ioparam.io_bounds.upper = end = datasects() - 1; 809 } else { 810 ioparam.io_bounds.upper = end = physsects() - 1; 811 } 812 } else { 813 ioparam.io_bounds.upper = end = cur_parts->etoc->efi_last_lba; 814 } 815 816 if (! (cur_ctlr->ctlr_flags & DKI_FMTVOL)) { 817 deflt = ioparam.io_bounds.lower; 818 start = input(FIO_BN, 819 "Enter starting block number", ':', 820 &ioparam, &deflt, DATA_INPUT); 821 ioparam.io_bounds.lower = start; 822 deflt = ioparam.io_bounds.upper; 823 end = input(FIO_BN, 824 "Enter ending block number", ':', 825 &ioparam, &deflt, DATA_INPUT); 826 } 827 /* 828 * Some disks can format tracks. Make sure the whole track is 829 * specified for them. 830 */ 831 if (cur_ctlr->ctlr_flags & DKI_FMTTRK) { 832 if (bn2s(start) != 0 || 833 bn2s(end) != sectors(bn2h(end)) - 1) { 834 err_print("Controller requires formatting of "); 835 err_print("entire tracks.\n"); 836 return (-1); 837 } 838 } 839 /* 840 * Check for mounted file systems in the format zone, and if we 841 * find any, make sure they are really serious. One potential 842 * problem with this would be that check() always returns 'yes' 843 * when running out of a file. However, it is actually ok 844 * because we don't let the program get started if there are 845 * mounted file systems and we are running from a file. 846 */ 847 if (checkmount(start, end)) { 848 err_print( 849 "Cannot format disk while it has mounted partitions.\n\n"); 850 return (-1); 851 } 852 /* 853 * check for partitions being used for swapping in format zone 854 */ 855 if (checkswap(start, end)) { 856 err_print("Cannot format disk while its partition are \ 857 currently being used for swapping.\n"); 858 return (-1); 859 } 860 if (SCSI && (format_time = scsi_format_time()) > 0) { 861 fmt_print( 862 "Ready to format. Formatting cannot be interrupted\n" 863 "and takes %d minutes (estimated). ", format_time); 864 865 } else if (cur_dtype->dtype_options & SUP_FMTTIME) { 866 /* 867 * Formatting time is (2 * time of 1 spin * number of 868 * tracks) + (step rate * number of cylinders) rounded 869 * up to the nearest minute. Note, a 10% fudge factor 870 * is thrown in for insurance. 871 */ 872 if (cur_dtype->dtype_fmt_time == 0) 873 cur_dtype->dtype_fmt_time = 2; 874 875 format_tracks = ((end-start) / cur_dtype->dtype_nsect) + 1; 876 format_cyls = format_tracks / cur_dtype->dtype_nhead; 877 format_tracks = format_tracks * cur_dtype->dtype_fmt_time; 878 879 /* 880 * ms. 881 */ 882 format_time = ((60000 / cur_dtype->dtype_rpm) +1) * 883 format_tracks + format_cyls * 7; 884 /* 885 * 20% done tick (sec) 886 */ 887 format_interval = format_time / 5000; 888 /* 889 * min. 890 */ 891 format_time = (format_time + 59999) / 60000; 892 893 /* 894 * Check format time values and make adjustments 895 * to prevent sleeping too long (forever?) or 896 * too short. 897 */ 898 if (format_time <= 1) { 899 /* 900 * Format time is less than 1 min.. 901 */ 902 format_time = 1; 903 } 904 905 if (format_interval < 11) { 906 /* Format time is less than 1 minute. */ 907 if (format_interval < 2) 908 format_interval = 2; /* failsafe */ 909 format_interval = 10; 910 } else { 911 /* Format time is greater than 1 minute. */ 912 format_interval -= 10; 913 } 914 915 fmt_print( 916 "Ready to format. Formatting cannot be interrupted\n" 917 "and takes %d minutes (estimated). ", format_time); 918 } else { 919 fmt_print( 920 "Ready to format. Formatting cannot be interrupted.\n"); 921 } 922 if (check("Continue")) { 923 return (-1); 924 } 925 926 /* 927 * Print the time so that the user will know when format started. 928 * Lock out interrupts. This could be a problem, since it could 929 * cause the user to sit for quite awhile with no control, but we 930 * don't have any other good way of keeping his gun from going off. 931 */ 932 clock = time((time_t *)0); 933 fmt_print("Beginning format. The current time is %s\n", 934 ctime(&clock)); 935 enter_critical(); 936 /* 937 * Mark the defect list dirty so it will be rewritten when we are 938 * done. It is possible to qualify this so it doesn't always 939 * get rewritten, but it's not worth the trouble. 940 * Note: no defect lists for embedded scsi drives. 941 */ 942 if (!EMBEDDED_SCSI) { 943 cur_list.flags |= LIST_DIRTY; 944 } 945 /* 946 * If we are formatting over any of the labels, mark the label 947 * dirty so it will be rewritten. 948 */ 949 if (cur_disk->label_type == L_TYPE_SOLARIS) { 950 if (start < totalsects() && end >= datasects()) { 951 if (cur_disk->disk_flags & DSK_LABEL) 952 cur_flags |= LABEL_DIRTY; 953 } 954 } else if (cur_disk->label_type == L_TYPE_EFI) { 955 if (start < 34) { 956 if (cur_disk->disk_flags & DSK_LABEL) 957 cur_flags |= LABEL_DIRTY; 958 } 959 } 960 if (start == 0) { 961 cur_flags |= LABEL_DIRTY; 962 } 963 /* 964 * Do the format. bugid 1009138 removed the use of fork to 965 * background the format and print a tick. 966 */ 967 968 status = (*cur_ops->op_format)(start, end, &cur_list); 969 if (status) { 970 exit_critical(); 971 err_print("failed\n"); 972 return (-1); 973 } 974 fmt_print("done\n"); 975 if (option_msg && diag_msg) { 976 clock = time((time_t *)0); 977 fmt_print("The current time is %s\n", ctime(&clock)); 978 } 979 cur_flags |= DISK_FORMATTED; 980 /* 981 * If the defect list or label is dirty, write them out again. 982 * Note, for SCSI we have to wait til now to load defect list 983 * since we can't access it until after formatting a virgin disk. 984 */ 985 /* enter_critical(); */ 986 if (cur_list.flags & LIST_RELOAD) { 987 assert(!EMBEDDED_SCSI); 988 if (*cur_ops->op_ex_man == NULL || 989 (*cur_ops->op_ex_man)(&cur_list)) { 990 err_print("Warning: unable to reload defect list\n"); 991 cur_list.flags &= ~LIST_DIRTY; 992 return (-1); 993 } 994 cur_list.flags |= LIST_DIRTY; 995 } 996 997 if (cur_list.flags & LIST_DIRTY) { 998 assert(!EMBEDDED_SCSI); 999 write_deflist(&cur_list); 1000 cur_list.flags = 0; 1001 } 1002 if (cur_flags & LABEL_DIRTY) { 1003 (void) write_label(); 1004 cur_flags &= ~LABEL_DIRTY; 1005 } 1006 /* 1007 * Come up for air, since the verify step does not need to 1008 * be atomic (it does it's own lockouts when necessary). 1009 */ 1010 exit_critical(); 1011 /* 1012 * If we are supposed to verify, we do the 'write' test over 1013 * the format zone. The rest of the analysis parameters are 1014 * left the way they were. 1015 */ 1016 if (scan_auto) { 1017 scan_entire = 0; 1018 scan_lower = start; 1019 scan_upper = end; 1020 fmt_print("\nVerifying media..."); 1021 status = do_scan(SCAN_PATTERN, F_SILENT); 1022 } 1023 /* 1024 * If the defect list or label is dirty, write them out again. 1025 */ 1026 if (cur_list.flags & LIST_DIRTY) { 1027 assert(!EMBEDDED_SCSI); 1028 cur_list.flags = 0; 1029 write_deflist(&cur_list); 1030 } 1031 if (cur_flags & LABEL_DIRTY) { 1032 cur_flags &= ~LABEL_DIRTY; 1033 (void) write_label(); 1034 } 1035 return (status); 1036 } 1037 1038 /* 1039 * This routine implements the 'repair' command. It allows the user 1040 * to reallocate sectors on the disk that have gone bad. 1041 */ 1042 int 1043 c_repair() 1044 { 1045 diskaddr_t bn; 1046 int status; 1047 u_ioparam_t ioparam; 1048 char buf[SECSIZE]; 1049 int buf_is_good; 1050 int block_has_error; 1051 int i; 1052 1053 /* 1054 * There must be a current disk type (and therefore a current disk). 1055 */ 1056 if (cur_dtype == NULL) { 1057 err_print("Current Disk Type is not set.\n"); 1058 return (-1); 1059 } 1060 /* 1061 * The current disk must be formatted for repair to work. 1062 */ 1063 if (!(cur_flags & DISK_FORMATTED)) { 1064 err_print("Current Disk is unformatted.\n"); 1065 return (-1); 1066 } 1067 /* 1068 * Check for a valid fdisk table entry for Solaris 1069 */ 1070 if (!good_fdisk()) { 1071 err_print("Please run fdisk first.\n"); 1072 return (-1); 1073 } 1074 /* 1075 * Repair is an optional command for controllers, so it may 1076 * not be supported. 1077 */ 1078 if (cur_ops->op_repair == NULL) { 1079 err_print("Controller does not support repairing.\n"); 1080 err_print("or disk supports automatic defect management.\n"); 1081 return (-1); 1082 } 1083 /* 1084 * There must be a defect list for non-embedded scsi devices, 1085 * since we will add to it. 1086 */ 1087 if (!EMBEDDED_SCSI && cur_list.list == NULL) { 1088 err_print("Current Defect List must be initialized.\n"); 1089 return (-1); 1090 } 1091 /* 1092 * Ask the user which sector has gone bad. 1093 */ 1094 ioparam.io_bounds.lower = 0; 1095 if (cur_disk->label_type == L_TYPE_SOLARIS) { 1096 ioparam.io_bounds.upper = physsects() - 1; 1097 } else { 1098 ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; 1099 } 1100 bn = input(FIO_BN, 1101 "Enter absolute block number of defect", ':', 1102 &ioparam, (int *)NULL, DATA_INPUT); 1103 /* 1104 * Check to see if there is a mounted file system over the 1105 * specified sector. If there is, make sure the user is 1106 * really serious. 1107 */ 1108 if (checkmount(bn, bn)) { 1109 if (check("Repair is in a mounted partition, continue")) 1110 return (-1); 1111 } 1112 /* 1113 * check for partitions being used for swapping in format zone 1114 */ 1115 if (checkswap(bn, bn)) { 1116 if (check("Repair is in a partition which is currently \ 1117 being used for swapping.\ncontinue")) 1118 return (-1); 1119 } 1120 1121 /* 1122 * Try to read the sector before repairing it. If we can 1123 * get good data out of it, we can write that data back 1124 * after the repair. If the sector looks ok, ask the 1125 * user to confirm the repair, since it doesn't appear 1126 * necessary. Try reading the block several times to 1127 * see if we can read it consistently. 1128 * 1129 * First, let's see if the block appears to have problems... 1130 */ 1131 block_has_error = 1; 1132 for (i = 0; i < 5; i++) { 1133 status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 1134 1, buf, (F_SILENT | F_ALLERRS), NULL); 1135 if (status) 1136 break; /* one of the tries failed */ 1137 } 1138 if (status == 0) { 1139 block_has_error = 0; 1140 if (check("\ 1141 This block doesn't appear to be bad. Repair it anyway")) { 1142 return (0); 1143 } 1144 } 1145 /* 1146 * Last chance... 1147 */ 1148 if (check("Ready to repair defect, continue")) { 1149 return (-1); 1150 } 1151 /* 1152 * We're committed to repairing it. Try to get any good 1153 * data out of the block if possible. Note that we do 1154 * not set the F_ALLERRS flag. 1155 */ 1156 buf_is_good = 0; 1157 for (i = 0; i < 5; i++) { 1158 status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, 1159 1, buf, F_SILENT, NULL); 1160 if (status == 0) { 1161 buf_is_good = 1; 1162 break; 1163 } 1164 } 1165 /* 1166 * Lock out interrupts so the disk can't get out of sync with 1167 * the defect list. 1168 */ 1169 enter_critical(); 1170 1171 fmt_print("Repairing "); 1172 if (block_has_error) { 1173 fmt_print("%s error on ", buf_is_good ? "soft" : "hard"); 1174 } 1175 fmt_print("block %llu (", bn); 1176 pr_dblock(fmt_print, bn); 1177 fmt_print(")..."); 1178 /* 1179 * Do the repair. 1180 */ 1181 status = (*cur_ops->op_repair)(bn, F_NORMAL); 1182 if (status) { 1183 fmt_print("failed.\n\n"); 1184 } else { 1185 /* 1186 * The repair worked. Write the old data to the new 1187 * block if we were able to read it, otherwise 1188 * zero out the new block. If it looks like the 1189 * new block is bad, let the user know that, too. 1190 * Should we attempt auto-repair in this case? 1191 */ 1192 fmt_print("ok.\n"); 1193 if (!buf_is_good) { 1194 bzero(buf, SECSIZE); 1195 } 1196 status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, bn, 1197 1, buf, (F_SILENT | F_ALLERRS), NULL); 1198 if (status == 0) { 1199 status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, 1200 bn, 1, buf, (F_SILENT | F_ALLERRS), NULL); 1201 } 1202 if (status) { 1203 fmt_print("The new block %llu (", bn); 1204 pr_dblock(fmt_print, bn); 1205 fmt_print(") also appears defective.\n"); 1206 } 1207 fmt_print("\n"); 1208 /* 1209 * Add the bad sector to the defect list, write out 1210 * the defect list, and kill off the working list so 1211 * it will get synced up with the current defect list 1212 * next time we need it. 1213 * 1214 * For embedded scsi, we don't require a defect list. 1215 * However, if we have one, add the defect if the 1216 * list includes the grown list. If not, kill it 1217 * to force a resync if we need the list later. 1218 */ 1219 if (EMBEDDED_SCSI) { 1220 if (cur_list.list != NULL) { 1221 if (cur_list.flags & LIST_PGLIST) { 1222 add_ldef(bn, &cur_list); 1223 } else { 1224 kill_deflist(&cur_list); 1225 } 1226 } 1227 } else if (cur_ctype->ctype_flags & CF_WLIST) { 1228 kill_deflist(&cur_list); 1229 if (*cur_ops->op_ex_cur != NULL) { 1230 (*cur_ops->op_ex_cur)(&cur_list); 1231 fmt_print("Current list updated\n"); 1232 } 1233 } else { 1234 add_ldef(bn, &cur_list); 1235 write_deflist(&cur_list); 1236 } 1237 kill_deflist(&work_list); 1238 } 1239 exit_critical(); 1240 /* 1241 * Return status. 1242 */ 1243 return (status); 1244 } 1245 1246 /* 1247 * This routine implements the 'show' command. It translates a disk 1248 * block given in any format into decimal, hexadecimal, and 1249 * cylinder/head/sector format. 1250 */ 1251 int 1252 c_show() 1253 { 1254 u_ioparam_t ioparam; 1255 daddr_t bn; 1256 1257 /* 1258 * There must be a current disk type, so we will know the geometry. 1259 */ 1260 if (cur_dtype == NULL) { 1261 err_print("Current Disk Type is not set.\n"); 1262 return (-1); 1263 } 1264 /* 1265 * Ask the user for a disk block. 1266 */ 1267 ioparam.io_bounds.lower = 0; 1268 if (cur_disk->label_type == L_TYPE_SOLARIS) { 1269 ioparam.io_bounds.upper = physsects() - 1; 1270 } else { 1271 ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; 1272 } 1273 bn = (daddr_t)input(FIO_BN, "Enter a disk block", ':', 1274 &ioparam, (int *)NULL, DATA_INPUT); 1275 /* 1276 * Echo it back. 1277 */ 1278 fmt_print("Disk block = %ld = 0x%lx = (", bn, bn); 1279 pr_dblock(fmt_print, bn); 1280 fmt_print(")\n\n"); 1281 return (0); 1282 } 1283 1284 /* 1285 * This routine implements the 'label' command. It writes the 1286 * primary and backup labels onto the current disk. 1287 */ 1288 int 1289 c_label() 1290 { 1291 int status; 1292 int deflt, *defltptr = NULL; 1293 1294 /* 1295 * There must be a current disk type (and therefore a current disk). 1296 */ 1297 if (cur_dtype == NULL) { 1298 err_print("Current Disk Type is not set.\n"); 1299 return (-1); 1300 } 1301 /* 1302 * The current disk must be formatted to label it. 1303 */ 1304 if (!(cur_flags & DISK_FORMATTED)) { 1305 err_print("Current Disk is unformatted.\n"); 1306 return (-1); 1307 } 1308 /* 1309 * Check for a valid fdisk table entry for Solaris 1310 */ 1311 if (!good_fdisk()) { 1312 err_print("Please run fdisk first.\n"); 1313 return (-1); 1314 } 1315 /* 1316 * Check to see if there are any mounted file systems anywhere 1317 * on the current disk. If so, refuse to label the disk, but 1318 * only if the partitions would change for the mounted partitions. 1319 * 1320 */ 1321 if (checkmount((daddr_t)-1, (daddr_t)-1)) { 1322 /* Bleagh, too descriptive */ 1323 if (check_label_with_mount()) { 1324 err_print("Cannot label disk while it has " 1325 "mounted partitions.\n\n"); 1326 return (-1); 1327 } 1328 } 1329 1330 /* 1331 * check to see if there any partitions being used for swapping 1332 * on the current disk. If so, refuse to label the disk, but 1333 * only if the partitions would change for the mounted partitions. 1334 */ 1335 if (checkswap((daddr_t)-1, (daddr_t)-1)) { 1336 if (check_label_with_swap()) { 1337 err_print("Cannot label disk while its " 1338 "partitions are currently being used for " 1339 "swapping.\n"); 1340 return (-1); 1341 } 1342 } 1343 1344 1345 /* 1346 * If there is not a current partition map, warn the user we 1347 * are going to use the default. The default is the first 1348 * partition map we encountered in the data file. If there is 1349 * no default we give up. 1350 */ 1351 if (cur_parts == NULL) { 1352 fmt_print("Current Partition Table is not set, " 1353 "using default.\n"); 1354 cur_disk->disk_parts = cur_parts = cur_dtype->dtype_plist; 1355 if (cur_parts == NULL) { 1356 err_print("No default available, cannot label.\n"); 1357 return (-1); 1358 } 1359 } 1360 /* 1361 * If expert (-e) mode, then ask user if they wish 1362 * to change the current solaris label into an EFI one 1363 */ 1364 if (expert_mode) { 1365 #if defined(_SUNOS_VTOC_8) 1366 int i; 1367 #endif 1368 int choice; 1369 u_ioparam_t ioparam; 1370 struct vtoc vtoc; 1371 struct dk_label label; 1372 struct dk_gpt *vtoc64; 1373 struct efi_info efinfo; 1374 struct disk_type *dptr; 1375 1376 /* If capacity > 1TB then offer no choice */ 1377 if (cur_label == L_TYPE_EFI) { 1378 if (cur_dtype->capacity > INFINITY) { 1379 goto expert_end; 1380 } 1381 } 1382 /* Ask user what label to use */ 1383 fmt_print("[0] SMI Label\n"); 1384 fmt_print("[1] EFI Label\n"); 1385 ioparam.io_bounds.lower = 0; 1386 ioparam.io_bounds.upper = 1; 1387 if (cur_label == L_TYPE_SOLARIS) 1388 deflt = 0; 1389 else 1390 deflt = 1; 1391 defltptr = &deflt; 1392 choice = input(FIO_INT, "Specify Label type", ':', 1393 &ioparam, defltptr, DATA_INPUT); 1394 if ((choice == 0) && (cur_label == L_TYPE_SOLARIS)) { 1395 goto expert_end; 1396 } else if ((choice == 1) && (cur_label == L_TYPE_EFI)) { 1397 goto expert_end; 1398 } 1399 switch (choice) { 1400 case 0: 1401 /* 1402 * EFI label to SMI label 1403 */ 1404 if (cur_dtype->capacity > INFINITY) { 1405 fmt_print("SMI Label not supported on this disk\n"); 1406 return (-1); 1407 } 1408 1409 dptr = auto_sense(cur_file, 1, &label); 1410 pcyl = label.dkl_pcyl; 1411 ncyl = label.dkl_ncyl; 1412 acyl = label.dkl_acyl; 1413 nhead = label.dkl_nhead; 1414 nsect = label.dkl_nsect; 1415 1416 if (dptr == NULL) { 1417 fmt_print("Autoconfiguration failed.\n"); 1418 return (-1); 1419 } 1420 1421 if (cur_disk->fdisk_part.systid == EFI_PMBR) { 1422 fmt_print("You must use fdisk to delete the current " 1423 "EFI partition and create a new\n" 1424 "Solaris partition before you can convert the " 1425 "label\n"); 1426 return (-1); 1427 } 1428 1429 cur_label = L_TYPE_SOLARIS; 1430 cur_disk->label_type = L_TYPE_SOLARIS; 1431 free(cur_parts->etoc); 1432 free(cur_parts); 1433 dptr->dtype_next = cur_dtype->dtype_next; 1434 free(cur_disk->disk_type); 1435 cur_disk->disk_type = dptr; 1436 cur_disk->disk_parts = dptr->dtype_plist; 1437 cur_dtype = dptr; 1438 cur_parts = dptr->dtype_plist; 1439 dptr->dtype_next = NULL; 1440 break; 1441 case 1: 1442 /* 1443 * SMI label to EFI label 1444 */ 1445 #ifdef i386 1446 fmt_print("WARNING: converting this device to EFI labels will " 1447 "erase all current fdisk\n" 1448 "partition information."); 1449 if (check(" Continue")) { 1450 return (-1); 1451 } 1452 #else /* i386 */ 1453 if (check("Ready to label disk; continue")) { 1454 return (-1); 1455 } 1456 #endif /* i386 */ 1457 1458 if (get_disk_info(cur_file, &efinfo) != 0) { 1459 return (-1); 1460 } 1461 (void) memset((char *)&label, 0, sizeof (struct dk_label)); 1462 label.dkl_pcyl = pcyl; 1463 label.dkl_ncyl = ncyl; 1464 label.dkl_acyl = acyl; 1465 #if defined(_SUNOS_VTOC_16) 1466 label.dkl_bcyl = bcyl; 1467 #endif /* defined(_SUNOC_VTOC_16) */ 1468 label.dkl_nhead = nhead; 1469 label.dkl_nsect = nsect; 1470 #if defined(_SUNOS_VTOC_8) 1471 for (i = 0; i < NDKMAP; i++) { 1472 label.dkl_map[i] = cur_parts->pinfo_map[i]; 1473 } 1474 #endif /* defined(_SUNOS_VTOC_8) */ 1475 label.dkl_magic = DKL_MAGIC; 1476 label.dkl_vtoc = cur_parts->vtoc; 1477 if (label_to_vtoc(&vtoc, &label) == -1) { 1478 return (-1); 1479 } 1480 if (SMI_vtoc_to_EFI(cur_file, &vtoc64, &vtoc) == -1) { 1481 return (-1); 1482 } 1483 if (efi_write(cur_file, vtoc64) != 0) { 1484 err_check(vtoc64); 1485 err_print("Warning: error writing EFI.\n"); 1486 return (-1); 1487 } 1488 /* 1489 * copy over the EFI vtoc onto the SMI vtoc and return 1490 * okay. 1491 */ 1492 cur_parts->etoc = vtoc64; 1493 cur_label = L_TYPE_EFI; 1494 cur_disk->label_type = L_TYPE_EFI; 1495 (void) strlcpy(cur_dtype->vendor, efinfo.vendor, 9); 1496 (void) strlcpy(cur_dtype->product, efinfo.product, 17); 1497 (void) strlcpy(cur_dtype->revision, efinfo.revision, 5); 1498 cur_dtype->capacity = efinfo.capacity; 1499 free(cur_dtype->dtype_asciilabel); 1500 ncyl = pcyl = nsect = psect = acyl = psect = phead = 0; 1501 1502 return (0); 1503 } 1504 } 1505 1506 expert_end: 1507 /* 1508 * Make sure the user is serious. 1509 */ 1510 if (check("Ready to label disk, continue")) { 1511 return (-1); 1512 } 1513 /* 1514 * Write the labels out (this will also notify unix) and 1515 * return status. 1516 */ 1517 fmt_print("\n"); 1518 if (status = write_label()) 1519 err_print("Label failed.\n"); 1520 return (status); 1521 } 1522 1523 /* 1524 * This routine implements the 'analyze' command. It simply runs 1525 * the analyze menu. 1526 */ 1527 int 1528 c_analyze() 1529 { 1530 1531 /* 1532 * There must be a current disk type (and therefor a current disk). 1533 */ 1534 if (cur_dtype == NULL) { 1535 err_print("Current Disk Type is not set.\n"); 1536 return (-1); 1537 } 1538 cur_menu++; 1539 last_menu = cur_menu; 1540 1541 /* 1542 * Run the menu. 1543 */ 1544 run_menu(menu_analyze, "ANALYZE", "analyze", 0); 1545 cur_menu--; 1546 return (0); 1547 } 1548 1549 /* 1550 * This routine implements the 'defect' command. It simply runs 1551 * the defect menu. 1552 */ 1553 int 1554 c_defect() 1555 { 1556 int i; 1557 1558 /* 1559 * There must be a current disk type (and therefor a current disk). 1560 */ 1561 if (cur_dtype == NULL) { 1562 err_print("Current Disk Type is not set.\n"); 1563 return (-1); 1564 } 1565 1566 /* 1567 * Check for the defect management and list management ops and 1568 * display appropriate message. 1569 */ 1570 if ((cur_ops->op_ex_man == NULL) && (cur_ops->op_ex_cur == NULL) && 1571 (cur_ops->op_create == NULL) && (cur_ops->op_wr_cur == NULL)) { 1572 err_print("Controller does not support defect management\n"); 1573 err_print("or disk supports automatic defect management.\n"); 1574 return (-1); 1575 } 1576 cur_menu++; 1577 last_menu = cur_menu; 1578 1579 /* 1580 * Lock out interrupt while we manipulate the defect lists. 1581 */ 1582 enter_critical(); 1583 /* 1584 * If the working list is null but there is a current list, 1585 * update the working list to be a copy of the current list. 1586 */ 1587 if ((work_list.list == NULL) && (cur_list.list != NULL)) { 1588 work_list.header = cur_list.header; 1589 work_list.list = (struct defect_entry *)zalloc( 1590 LISTSIZE(work_list.header.count) * SECSIZE); 1591 for (i = 0; i < work_list.header.count; i++) 1592 *(work_list.list + i) = *(cur_list.list + i); 1593 work_list.flags = cur_list.flags & LIST_PGLIST; 1594 } 1595 exit_critical(); 1596 /* 1597 * Run the menu. 1598 */ 1599 run_menu(menu_defect, "DEFECT", "defect", 0); 1600 cur_menu--; 1601 1602 /* 1603 * If the user has modified the working list but not committed 1604 * it, warn him that he is probably making a mistake. 1605 */ 1606 if (work_list.flags & LIST_DIRTY) { 1607 if (!EMBEDDED_SCSI) { 1608 err_print( 1609 "Warning: working defect list modified; but not committed.\n"); 1610 if (!check( 1611 "Do you wish to commit changes to current defect list")) 1612 (void) do_commit(); 1613 } 1614 } 1615 return (0); 1616 } 1617 1618 /* 1619 * This routine implements the 'backup' command. It allows the user 1620 * to search for backup labels on the current disk. This is useful 1621 * if the primary label was lost and the user wishes to recover the 1622 * partition information for the disk. The disk is relabeled and 1623 * the current defect list is written out if a backup label is found. 1624 */ 1625 int 1626 c_backup() 1627 { 1628 struct dk_label label; 1629 struct disk_type *dtype; 1630 struct partition_info *parts, *plist; 1631 daddr_t bn; 1632 int sec, head, i; 1633 1634 /* 1635 * There must be a current disk type (and therefore a current disk). 1636 */ 1637 if (cur_dtype == NULL) { 1638 err_print("Current Disk Type is not set.\n"); 1639 return (-1); 1640 } 1641 /* 1642 * The disk must be formatted to read backup labels. 1643 */ 1644 if (!(cur_flags & DISK_FORMATTED)) { 1645 err_print("Current Disk is unformatted.\n"); 1646 return (-1); 1647 } 1648 /* 1649 * Check for a valid fdisk table entry for Solaris 1650 */ 1651 if (!good_fdisk()) { 1652 err_print("Please run fdisk first.\n"); 1653 return (-1); 1654 } 1655 /* 1656 * If we found a primary label on this disk, make sure 1657 * the user is serious. 1658 */ 1659 if (cur_disk->label_type == L_TYPE_EFI) { 1660 if (((cur_disk->disk_parts->etoc->efi_flags & 1661 EFI_GPT_PRIMARY_CORRUPT) == 0) && 1662 check("Disk has a primary label, still continue")) 1663 return (-1); 1664 fmt_print("Restoring primary label.\n"); 1665 if (write_label()) { 1666 err_print("Failed\n"); 1667 return (-1); 1668 } 1669 return (0); 1670 } else if (((cur_disk->disk_flags & (DSK_LABEL | DSK_LABEL_DIRTY)) == 1671 DSK_LABEL) && 1672 (check("Disk has a primary label, still continue"))) { 1673 return (-1); 1674 } 1675 fmt_print("Searching for backup labels..."); 1676 (void) fflush(stdout); 1677 /* 1678 * Some disks have the backup labels in a strange place. 1679 */ 1680 if (cur_ctype->ctype_flags & CF_BLABEL) 1681 head = 2; 1682 else 1683 head = nhead - 1; 1684 /* 1685 * Loop through each copy of the backup label. 1686 */ 1687 for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect)); 1688 sec += 2) { 1689 bn = chs2bn(ncyl + acyl - 1, head, sec) + solaris_offset; 1690 /* 1691 * Attempt to read it. 1692 */ 1693 if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, (diskaddr_t)bn, 1694 1, (char *)&label, F_NORMAL, NULL)) { 1695 continue; 1696 } 1697 /* 1698 * Verify that it is a reasonable label. 1699 */ 1700 if (!checklabel(&label)) 1701 continue; 1702 if (trim_id(label.dkl_asciilabel)) 1703 continue; 1704 /* 1705 * Lock out interrupts while we manipulate lists. 1706 */ 1707 enter_critical(); 1708 fmt_print("found.\n"); 1709 /* 1710 * Find out which disk type the backup label claims. 1711 */ 1712 for (dtype = cur_ctype->ctype_dlist; dtype != NULL; 1713 dtype = dtype->dtype_next) 1714 if (dtype_match(&label, dtype)) 1715 break; 1716 /* 1717 * If it disagrees with our current type, something 1718 * real bad is happening. 1719 */ 1720 if (dtype != cur_dtype) { 1721 if (dtype == NULL) { 1722 fmt_print("\ 1723 Unknown disk type in backup label\n"); 1724 exit_critical(); 1725 return (-1); 1726 } 1727 fmt_print("Backup label claims different type:\n"); 1728 fmt_print(" <%s cyl %d alt %d hd %d sec %d>\n", 1729 label.dkl_asciilabel, label.dkl_ncyl, 1730 label.dkl_acyl, label.dkl_nhead, 1731 label.dkl_nsect); 1732 if (check("Continue")) { 1733 exit_critical(); 1734 return (-1); 1735 } 1736 cur_dtype = dtype; 1737 } 1738 /* 1739 * Try to match the partition map with a known map. 1740 */ 1741 for (parts = dtype->dtype_plist; parts != NULL; 1742 parts = parts->pinfo_next) 1743 if (parts_match(&label, parts)) 1744 break; 1745 /* 1746 * If we couldn't match it, allocate space for a new one, 1747 * fill in the info, and add it to the list. The name 1748 * for the new map is derived from the disk name. 1749 */ 1750 if (parts == NULL) { 1751 parts = (struct partition_info *) 1752 zalloc(sizeof (struct partition_info)); 1753 plist = dtype->dtype_plist; 1754 if (plist == NULL) 1755 dtype->dtype_plist = parts; 1756 else { 1757 while (plist->pinfo_next != NULL) 1758 plist = plist->pinfo_next; 1759 plist->pinfo_next = parts; 1760 } 1761 parts->pinfo_name = alloc_string("original"); 1762 for (i = 0; i < NDKMAP; i++) 1763 1764 #if defined(_SUNOS_VTOC_8) 1765 parts->pinfo_map[i] = label.dkl_map[i]; 1766 1767 #elif defined(_SUNOS_VTOC_16) 1768 parts->pinfo_map[i].dkl_cylno = 1769 label.dkl_vtoc.v_part[i].p_start / spc(); 1770 parts->pinfo_map[i].dkl_nblk = 1771 label.dkl_vtoc.v_part[i].p_size; 1772 #else 1773 #error No VTOC layout defined. 1774 #endif /* defined(_SUNOS_VTOC_8) */ 1775 parts->vtoc = label.dkl_vtoc; 1776 } 1777 /* 1778 * We now have a partition map. Make it the current map. 1779 */ 1780 cur_disk->disk_parts = cur_parts = parts; 1781 exit_critical(); 1782 /* 1783 * Rewrite the labels and defect lists, as appropriate. 1784 */ 1785 if (EMBEDDED_SCSI) { 1786 fmt_print("Restoring primary label.\n"); 1787 if (write_label()) 1788 return (-1); 1789 } else { 1790 fmt_print("Restoring primary label and defect list.\n"); 1791 if (write_label()) 1792 return (-1); 1793 if (cur_list.list != NULL) 1794 write_deflist(&cur_list); 1795 } 1796 fmt_print("\n"); 1797 return (0); 1798 } 1799 /* 1800 * If we didn't find any backup labels, say so. 1801 */ 1802 fmt_print("not found.\n\n"); 1803 return (0); 1804 } 1805 1806 /* 1807 * This routine is called by c_verify() for an EFI labeled disk 1808 */ 1809 static int 1810 c_verify_efi() 1811 { 1812 struct efi_info efi_info; 1813 struct partition_info tmp_pinfo; 1814 int status; 1815 1816 status = read_efi_label(cur_file, &efi_info); 1817 if (status != 0) { 1818 err_print("Warning: Could not read label.\n"); 1819 return (-1); 1820 } 1821 if (cur_parts->etoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) { 1822 err_print("Reading the primary EFI GPT label "); 1823 err_print("failed. Using backup label.\n"); 1824 err_print("Use the 'backup' command to restore "); 1825 err_print("the primary label.\n"); 1826 } 1827 tmp_pinfo.etoc = efi_info.e_parts; 1828 fmt_print("\n"); 1829 if (cur_parts->etoc->efi_parts[8].p_name) { 1830 fmt_print("Volume name = <%8s>\n", 1831 cur_parts->etoc->efi_parts[8].p_name); 1832 } else { 1833 fmt_print("Volume name = < >\n"); 1834 } 1835 fmt_print("ascii name = "); 1836 print_efi_string(efi_info.vendor, efi_info.product, 1837 efi_info.revision, efi_info.capacity); 1838 fmt_print("\n"); 1839 1840 fmt_print("bytes/sector = %d\n", DEV_BSIZE); 1841 fmt_print("sectors = %llu\n", cur_parts->etoc->efi_last_lba); 1842 fmt_print("accessible sectors = %llu\n", 1843 cur_parts->etoc->efi_last_u_lba); 1844 1845 print_map(&tmp_pinfo); 1846 return (0); 1847 } 1848 1849 /* 1850 * This routine implements the 'verify' command. It allows the user 1851 * to read the labels on the current disk. 1852 */ 1853 int 1854 c_verify() 1855 { 1856 struct dk_label p_label, b_label, *label; 1857 struct partition_info tmp_pinfo; 1858 daddr_t bn; 1859 int sec, head, i, status; 1860 int p_label_bad = 0; 1861 int b_label_bad = 0; 1862 int p_label_found = 0; 1863 int b_label_found = 0; 1864 char id_str[128]; 1865 1866 /* 1867 * There must be a current disk type (and therefore a current disk). 1868 */ 1869 if (cur_dtype == NULL) { 1870 err_print("Current Disk Type is not set.\n"); 1871 return (-1); 1872 } 1873 /* 1874 * The disk must be formatted to read labels. 1875 */ 1876 if (!(cur_flags & DISK_FORMATTED)) { 1877 err_print("Current Disk is unformatted.\n"); 1878 return (-1); 1879 } 1880 /* 1881 * Check for a valid fdisk table entry for Solaris 1882 */ 1883 if (!good_fdisk()) { 1884 err_print("Please run fdisk first.\n"); 1885 return (-1); 1886 } 1887 /* 1888 * Branch off here if the disk is EFI labelled. 1889 */ 1890 if (cur_label == L_TYPE_EFI) { 1891 return (c_verify_efi()); 1892 } 1893 /* 1894 * Attempt to read the primary label. 1895 */ 1896 status = read_label(cur_file, &p_label); 1897 if (status == -1) { 1898 err_print("Warning: Could not read primary label.\n"); 1899 p_label_bad = 1; 1900 } else { 1901 /* 1902 * Verify that it is a reasonable label. 1903 */ 1904 /* 1905 * Save complete ascii string for printing later. 1906 */ 1907 (void) strncpy(id_str, p_label.dkl_asciilabel, 128); 1908 1909 if ((!checklabel((struct dk_label *)&p_label)) || 1910 (trim_id(p_label.dkl_asciilabel))) { 1911 err_print("\ 1912 Warning: Primary label appears to be corrupt.\n"); 1913 p_label_bad = 1; 1914 } else { 1915 p_label_found = 1; 1916 /* 1917 * Make sure it matches current label 1918 */ 1919 if ((!dtype_match(&p_label, cur_dtype)) || 1920 (!parts_match(&p_label, cur_parts))) { 1921 err_print("\ 1922 Warning: Primary label on disk appears to be different from\ncurrent label.\n"); 1923 p_label_bad = 1; 1924 } 1925 } 1926 } 1927 1928 /* 1929 * Read backup labels. 1930 * Some disks have the backup labels in a strange place. 1931 */ 1932 if (cur_ctype->ctype_flags & CF_BLABEL) 1933 head = 2; 1934 else 1935 head = nhead - 1; 1936 /* 1937 * Loop through each copy of the backup label. 1938 */ 1939 for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect)); 1940 sec += 2) { 1941 bn = chs2bn(ncyl + acyl - 1, head, sec) + solaris_offset; 1942 /* 1943 * Attempt to read it. 1944 */ 1945 if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, (diskaddr_t)bn, 1946 1, (char *)&b_label, F_NORMAL, NULL)) 1947 continue; 1948 /* 1949 * Verify that it is a reasonable label. 1950 */ 1951 if (!checklabel(&b_label)) 1952 continue; 1953 1954 /* 1955 * Save complete label only if no primary label exists 1956 */ 1957 if (!p_label_found) 1958 (void) strncpy(id_str, b_label.dkl_asciilabel, 128); 1959 1960 if (trim_id(b_label.dkl_asciilabel)) 1961 continue; 1962 b_label_found = 1; 1963 /* 1964 * Compare against primary label 1965 */ 1966 if (p_label_found) { 1967 if ((strcmp(b_label.dkl_asciilabel, 1968 p_label.dkl_asciilabel) != 0) || 1969 (b_label.dkl_ncyl != p_label.dkl_ncyl) || 1970 (b_label.dkl_acyl != p_label.dkl_acyl) || 1971 (b_label.dkl_nhead != p_label.dkl_nhead) || 1972 (b_label.dkl_nsect != p_label.dkl_nsect)) { 1973 b_label_bad = 1; 1974 } else { 1975 for (i = 0; i < NDKMAP; i++) { 1976 #if defined(_SUNOS_VTOC_8) 1977 if ((b_label.dkl_map[i].dkl_cylno != 1978 p_label.dkl_map[i].dkl_cylno) || 1979 (b_label.dkl_map[i].dkl_nblk != 1980 p_label.dkl_map[i].dkl_nblk)) { 1981 b_label_bad = 1; 1982 break; 1983 } 1984 1985 #elif defined(_SUNOS_VTOC_16) 1986 if ((b_label.dkl_vtoc.v_part[i].p_tag != 1987 p_label.dkl_vtoc.v_part[i].p_tag) || 1988 (b_label.dkl_vtoc.v_part[i].p_flag != 1989 p_label.dkl_vtoc.v_part[i].p_flag) || 1990 (b_label.dkl_vtoc.v_part[i].p_start != 1991 p_label.dkl_vtoc.v_part[i].p_start) || 1992 (b_label.dkl_vtoc.v_part[i].p_size != 1993 p_label.dkl_vtoc.v_part[i].p_size)) { 1994 b_label_bad = 1; 1995 break; 1996 } 1997 #else 1998 #error No VTOC layout defined. 1999 #endif /* defined(_SUNOS_VTOC_8) */ 2000 } 2001 } 2002 } 2003 if (b_label_bad) 2004 err_print( 2005 "Warning: Primary and backup labels do not match.\n"); 2006 break; 2007 } 2008 /* 2009 * If we didn't find any backup labels, say so. 2010 */ 2011 if (!b_label_found) 2012 err_print("Warning: Could not read backup labels.\n"); 2013 2014 if ((!b_label_found) || (p_label_bad) || (b_label_bad)) 2015 err_print("\n\ 2016 Warning: Check the current partitioning and 'label' the disk or use the\n\ 2017 \t 'backup' command.\n"); 2018 2019 /* 2020 * Print label information. 2021 */ 2022 if (p_label_found) { 2023 fmt_print("\nPrimary label contents:\n"); 2024 label = &p_label; 2025 } else if (b_label_found) { 2026 fmt_print("\nBackup label contents:\n"); 2027 label = &b_label; 2028 } else { 2029 return (0); 2030 } 2031 2032 /* 2033 * Must put info into partition_info struct for 2034 * for print routine. 2035 */ 2036 bzero(&tmp_pinfo, sizeof (struct partition_info)); 2037 for (i = 0; i < NDKMAP; i++) { 2038 2039 #if defined(_SUNOS_VTOC_8) 2040 tmp_pinfo.pinfo_map[i] = label->dkl_map[i]; 2041 2042 #elif defined(_SUNOS_VTOC_16) 2043 tmp_pinfo.pinfo_map[i].dkl_cylno = 2044 label->dkl_vtoc.v_part[i].p_start / spc(); 2045 tmp_pinfo.pinfo_map[i].dkl_nblk = 2046 label->dkl_vtoc.v_part[i].p_size; 2047 #else 2048 #error No VTOC layout defined. 2049 #endif /* defined(_SUNOS_VTOC_8) */ 2050 } 2051 tmp_pinfo.vtoc = label->dkl_vtoc; 2052 2053 fmt_print("\n"); 2054 fmt_print("Volume name = <%8s>\n", label->dkl_vtoc.v_volume); 2055 fmt_print("ascii name = <%s>\n", id_str); 2056 fmt_print("pcyl = %4d\n", label->dkl_pcyl); 2057 fmt_print("ncyl = %4d\n", label->dkl_ncyl); 2058 fmt_print("acyl = %4d\n", label->dkl_acyl); 2059 2060 #if defined(_SUNOS_VTOC_16) 2061 fmt_print("bcyl = %4d\n", label->dkl_bcyl); 2062 #endif /* defined(_SUNOS_VTOC_16) */ 2063 2064 fmt_print("nhead = %4d\n", label->dkl_nhead); 2065 fmt_print("nsect = %4d\n", label->dkl_nsect); 2066 2067 print_map(&tmp_pinfo); 2068 return (0); 2069 } 2070 2071 2072 /* 2073 * This command implements the inquiry command, for embedded SCSI 2074 * disks only, which issues a SCSI inquiry command, and 2075 * displays the resulting vendor, product id and revision level. 2076 */ 2077 int 2078 c_inquiry() 2079 { 2080 char inqbuf[255]; 2081 struct scsi_inquiry *inq; 2082 2083 assert(SCSI); 2084 2085 inq = (struct scsi_inquiry *)inqbuf; 2086 2087 if (uscsi_inquiry(cur_file, inqbuf, sizeof (inqbuf))) { 2088 err_print("Failed\n"); 2089 return (-1); 2090 } else { 2091 fmt_print("Vendor: "); 2092 print_buf(inq->inq_vid, sizeof (inq->inq_vid)); 2093 fmt_print("\nProduct: "); 2094 print_buf(inq->inq_pid, sizeof (inq->inq_pid)); 2095 fmt_print("\nRevision: "); 2096 print_buf(inq->inq_revision, sizeof (inq->inq_revision)); 2097 fmt_print("\n"); 2098 } 2099 2100 return (0); 2101 } 2102 2103 2104 /* 2105 * This routine allows the user to set the 8-character 2106 * volume name in the vtoc. It then writes both the 2107 * primary and backup labels onto the current disk. 2108 */ 2109 int 2110 c_volname() 2111 { 2112 int status; 2113 char *prompt; 2114 union { 2115 int xfoo; 2116 char defvolname[LEN_DKL_VVOL+1]; 2117 } x; 2118 char s1[MAXPATHLEN], nclean[MAXPATHLEN]; 2119 char *volname; 2120 2121 2122 /* 2123 * There must be a current disk type (and therefore a current disk). 2124 */ 2125 if (cur_dtype == NULL) { 2126 err_print("Current Disk Type is not set.\n"); 2127 return (-1); 2128 } 2129 /* 2130 * The current disk must be formatted to label it. 2131 */ 2132 if (!(cur_flags & DISK_FORMATTED)) { 2133 err_print("Current Disk is unformatted.\n"); 2134 return (-1); 2135 } 2136 /* 2137 * Check for a valid fdisk table entry for Solaris 2138 */ 2139 if (!good_fdisk()) { 2140 err_print("Please run fdisk first.\n"); 2141 return (-1); 2142 } 2143 /* 2144 * The current disk must be formatted to label it. 2145 */ 2146 if (cur_parts == NULL) { 2147 err_print( 2148 "Please select a partition map for the disk first.\n"); 2149 return (-1); 2150 } 2151 /* 2152 * Check to see if there are any mounted file systems anywhere 2153 * on the current disk. If so, refuse to label the disk, but 2154 * only if the partitions would change for the mounted partitions. 2155 * 2156 */ 2157 if (checkmount((daddr_t)-1, (daddr_t)-1)) { 2158 /* Bleagh, too descriptive */ 2159 if (check_label_with_mount()) { 2160 err_print( 2161 "Cannot label disk while it has mounted partitions.\n\n"); 2162 return (-1); 2163 } 2164 } 2165 /* 2166 * Check to see if there are partitions being used for swapping 2167 * on the current disk. If so, refuse to label the disk, but 2168 * only if the partitions would change for the swap partitions. 2169 * 2170 */ 2171 if (checkswap((daddr_t)-1, (daddr_t)-1)) { 2172 /* Bleagh, too descriptive */ 2173 if (check_label_with_swap()) { 2174 err_print( 2175 "Cannot label disk while its partitions are currently \ 2176 being used for swapping.\n\n"); 2177 return (-1); 2178 } 2179 } 2180 /* 2181 * Prompt for the disk volume name. 2182 */ 2183 prompt = "Enter 8-character volume name (remember quotes)"; 2184 bzero(x.defvolname, LEN_DKL_VVOL+1); 2185 bcopy(cur_disk->v_volume, x.defvolname, LEN_DKL_VVOL); 2186 /* 2187 * Get the input using "get_inputline" since 2188 * input would never return null string. 2189 */ 2190 fmt_print("%s[\"%s\"]:", prompt, x.defvolname); 2191 2192 /* 2193 * Get input from the user. 2194 */ 2195 get_inputline(nclean, MAXPATHLEN); 2196 clean_token(s1, nclean); 2197 /* 2198 * check for return. 2199 */ 2200 if (s1[0] == 0) { 2201 volname = x.defvolname; 2202 } else { 2203 /* 2204 * remove the " mark from volname. 2205 */ 2206 if (s1[0] == '"') { 2207 int i = 1; 2208 volname = &s1[1]; 2209 while (s1[i] != '"' && s1[i] != '\0') 2210 i++; 2211 s1[i] = '\0'; 2212 clean_token(nclean, volname); 2213 volname = nclean; 2214 } else { 2215 (void) sscanf(&s1[0], "%1024s", nclean); 2216 volname = nclean; 2217 }; 2218 } 2219 /* 2220 * Make sure the user is serious. 2221 */ 2222 if (check("Ready to label disk, continue")) { 2223 fmt_print("\n"); 2224 return (-1); 2225 } 2226 /* 2227 * Use the volume name chosen above 2228 */ 2229 bzero(cur_disk->v_volume, LEN_DKL_VVOL); 2230 bcopy(volname, cur_disk->v_volume, min((int)strlen(volname), 2231 LEN_DKL_VVOL)); 2232 if (cur_label == L_TYPE_EFI) { 2233 bzero(cur_parts->etoc->efi_parts[8].p_name, LEN_DKL_VVOL); 2234 bcopy(volname, cur_parts->etoc->efi_parts[8].p_name, 2235 LEN_DKL_VVOL); 2236 } 2237 /* 2238 * Write the labels out (this will also notify unix) and 2239 * return status. 2240 */ 2241 fmt_print("\n"); 2242 if (status = write_label()) 2243 err_print("Label failed.\n"); 2244 return (status); 2245 } 2246