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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2014 Andrew Stormont. 26 */ 27 28 /* 29 * rmf_menu.c : 30 * Command line options to rmformat are processed in this file. 31 */ 32 33 #include "rmformat.h" 34 #include <sys/smedia.h> 35 #include <priv_utils.h> 36 37 extern int32_t D_flag; 38 extern int32_t e_flag; 39 extern int32_t H_flag; 40 extern int32_t U_flag; 41 extern int32_t V_flag; 42 extern int32_t b_flag; 43 extern int32_t w_flag; 44 extern int32_t W_flag; 45 extern int32_t s_flag; 46 extern int32_t c_flag; 47 extern int32_t F_flag; 48 extern int32_t R_flag; 49 extern int32_t p_flag; 50 extern int32_t l_flag; 51 52 extern char *myname; 53 extern char *slice_file; 54 extern diskaddr_t repair_blk_no; 55 extern int32_t quick_format; 56 extern int32_t long_format; 57 extern int32_t force_format; 58 extern int32_t rw_protect_enable; 59 extern int32_t rw_protect_disable; 60 extern int32_t wp_enable_passwd; 61 extern int32_t wp_disable_passwd; 62 extern int32_t wp_enable; 63 extern int32_t wp_disable; 64 extern int32_t verify_write; 65 extern char *dev_name; 66 extern char *label; 67 extern int total_devices_found; 68 extern int removable_found; 69 char *global_intr_msg; 70 smmedium_prop_t med_info; 71 int vol_running; 72 73 extern void check_invalid_combinations(); 74 extern void check_invalid_combinations_again(int32_t); 75 extern void process_options(); 76 extern void get_passwd(struct smwp_state *wp, int32_t confirm); 77 extern int32_t valid_slice_file(smedia_handle_t, int32_t, char *, 78 struct extvtoc *); 79 extern void trap_SIGINT(); 80 extern void release_SIGINT(); 81 extern int32_t verify(smedia_handle_t handle, int32_t fd, 82 diskaddr_t start_sector, uint32_t nblocks, 83 char *buf, int32_t flag, int32_t blocksize, int32_t no_raw_rw); 84 extern void my_perror(char *err_string); 85 extern void write_default_label(smedia_handle_t, int32_t fd); 86 extern int find_device(int defer, char *tmpstr); 87 88 void overwrite_metadata(int32_t fd, smedia_handle_t handle); 89 90 int32_t write_sunos_label(int32_t fd, int32_t media_type); 91 92 int32_t my_open(char *device_name, int32_t flags); 93 int32_t check_and_unmount_vold(char *device_name, int32_t flag); 94 int32_t check_and_unmount_scsi(char *device_name, int32_t flag); 95 96 int32_t check_and_unmount_floppy(int32_t fd, int32_t flag); 97 int32_t get_confirmation(void); 98 99 100 static void process_F_flag(smedia_handle_t handle, int32_t fd); 101 static void process_w_flag(smedia_handle_t handle); 102 static void process_W_flag(smedia_handle_t handle); 103 static void process_R_flag(smedia_handle_t handle); 104 void process_p_flag(smedia_handle_t handle, int32_t fd); 105 static void process_c_flag(smedia_handle_t handle); 106 static void process_V_flag(smedia_handle_t handle, int32_t fd); 107 static void process_s_flag(smedia_handle_t, int32_t fd); 108 static void process_e_flag(smedia_handle_t handle); 109 static void process_H_flag(smedia_handle_t handle, int32_t fd); 110 static void process_D_flag(smedia_handle_t handle, int32_t fd); 111 static void process_b_flag(int32_t fd); 112 static void process_l_flag(void); 113 114 void 115 process_options() 116 { 117 int32_t fd; 118 smedia_handle_t handle; 119 int32_t m_scsi_umount = 0; 120 int32_t m_flp_umount = 0; 121 int32_t v_device_umount = 0; 122 int32_t umount_required = 0; 123 int32_t removable; 124 int32_t umount_failed = 0; 125 struct dk_minfo media; 126 127 check_invalid_combinations(); 128 129 if (l_flag && !dev_name) { 130 process_l_flag(); 131 return; 132 } 133 134 if (U_flag) { 135 if (!(F_flag || H_flag || D_flag)) { 136 F_flag = 1; 137 long_format = 1; 138 } 139 } 140 141 if (F_flag || w_flag || W_flag || R_flag || D_flag || H_flag || 142 V_flag || c_flag || b_flag || s_flag || e_flag) { 143 umount_required = 1; 144 } 145 146 fd = my_open(dev_name, O_RDONLY|O_NDELAY); 147 if (fd < 0) { 148 PERROR("Could not open device"); 149 (void) close(fd); 150 exit(1); 151 } 152 153 if (ioctl(fd, DKIOCREMOVABLE, &removable) < 0) { 154 PERROR("DKIOCREMOVABLE ioctl failed"); 155 (void) close(fd); 156 exit(1); 157 } 158 if (!removable) { 159 (void) fprintf(stderr, 160 gettext("Not a removable media device\n")); 161 (void) close(fd); 162 exit(1); 163 } 164 165 if (ioctl(fd, DKIOCGMEDIAINFO, &media) < 0) { 166 (void) fprintf(stderr, 167 gettext("No media in specified device\n")); 168 (void) close(fd); 169 exit(1); 170 } 171 172 /* Check if volume manager has mounted this */ 173 if (umount_required) { 174 v_device_umount = check_and_unmount_vold(dev_name, U_flag); 175 if (v_device_umount != 1) { 176 m_scsi_umount = check_and_unmount_scsi(dev_name, 177 U_flag); 178 if (m_scsi_umount != 1) { 179 m_flp_umount = check_and_unmount_floppy(fd, 180 U_flag); 181 if (m_flp_umount != 1) { 182 umount_failed = 1; 183 } 184 } 185 } 186 } 187 188 if (umount_required && U_flag && umount_failed) { 189 if (v_device_umount || m_scsi_umount || m_flp_umount) { 190 (void) fprintf(stderr, 191 gettext("Could not unmount device.\n")); 192 (void) close(fd); 193 exit(1); 194 } 195 } 196 197 if (umount_required && !U_flag) { 198 if (v_device_umount || m_scsi_umount || m_flp_umount) { 199 (void) fprintf(stderr, gettext("Device mounted.\n")); 200 (void) fprintf(stderr, 201 gettext("Requested operation can not be \ 202 performed on a mounted device.\n")); 203 (void) close(fd); 204 exit(1); 205 } 206 } 207 /* register the fd with the libsmedia */ 208 handle = smedia_get_handle(fd); 209 if (handle == NULL) { 210 (void) fprintf(stderr, 211 gettext("Failed to get libsmedia handle.\n")); 212 (void) close(fd); 213 exit(1); 214 } 215 216 if (smedia_get_medium_property(handle, &med_info) < 0) { 217 (void) fprintf(stderr, 218 gettext("Get medium property failed \n")); 219 (void) smedia_release_handle(handle); 220 (void) close(fd); 221 exit(1); 222 } 223 224 DPRINTF1("media type %x\n", med_info.sm_media_type); 225 DPRINTF1("media block size %x\n", med_info.sm_blocksize); 226 DPRINTF1("media capacity %u\n", (uint32_t)med_info.sm_capacity); 227 DPRINTF3("media cyl %d head %d sect %d\n", 228 med_info.sm_pcyl, med_info.sm_nhead, med_info.sm_nsect); 229 check_invalid_combinations_again(med_info.sm_media_type); 230 231 /* 232 * Special handling for pcmcia, sometimes open the file in 233 * read-write mode. 234 */ 235 236 if (med_info.sm_media_type == SM_PCMCIA_MEM) { 237 if (F_flag || H_flag || D_flag || (V_flag && verify_write)) { 238 (void) close(fd); 239 DPRINTF("Reopening device\n"); 240 fd = my_open(dev_name, O_RDWR|O_NDELAY); 241 if (fd < 0) { 242 PERROR("Could not open device"); 243 (void) smedia_release_handle(handle); 244 (void) close(fd); 245 exit(1); 246 } 247 } 248 } 249 250 if (med_info.sm_media_type == SM_PCMCIA_ATA) { 251 if (V_flag || c_flag) { 252 (void) fprintf(stderr, 253 gettext("Option not supported on PC ATA cards\n")); 254 (void) smedia_release_handle(handle); 255 (void) close(fd); 256 exit(1); 257 } 258 if (F_flag) { 259 /* same text as used by the format command */ 260 (void) fprintf(stderr, 261 gettext("Cannot format this drive. Please use your \ 262 Manufacturer supplied formatting utility.\n")); 263 (void) smedia_release_handle(handle); 264 (void) close(fd); 265 exit(1); 266 } 267 } 268 269 if (F_flag) 270 process_F_flag(handle, fd); 271 if (w_flag) 272 process_w_flag(handle); 273 if (W_flag) 274 process_W_flag(handle); 275 if (R_flag) 276 process_R_flag(handle); 277 if (p_flag) 278 process_p_flag(handle, fd); 279 if (D_flag) 280 process_D_flag(handle, fd); 281 if (H_flag) 282 process_H_flag(handle, fd); 283 if (V_flag) 284 process_V_flag(handle, fd); 285 if (c_flag) 286 process_c_flag(handle); 287 if (b_flag) 288 process_b_flag(fd); 289 if (s_flag) 290 process_s_flag(handle, fd); 291 if (e_flag) 292 process_e_flag(handle); 293 if (l_flag) { 294 process_l_flag(); 295 } 296 297 (void) smedia_release_handle(handle); 298 (void) close(fd); 299 } 300 301 /* 302 * This routine handles the F_flag. 303 * This options should not be used for floppy. However, 304 * if this option is used for floppy, the option will 305 * be forced to SM_FORMAT_HD and smedia_format is called. 306 * Note that smedia_format is a blocked mode format and it 307 * returns only after the complete formatting is over. 308 */ 309 310 static void 311 process_F_flag(smedia_handle_t handle, int32_t fd) 312 { 313 uint32_t format_flag = 0; 314 int32_t old_per = 0; 315 int32_t new_per, ret_val; 316 317 if (force_format) { 318 (void) fprintf(stderr, 319 gettext("Formatting disk.\n")); 320 } else { 321 (void) fprintf(stderr, 322 gettext("Formatting will erase all the data on disk.\n")); 323 if (!get_confirmation()) 324 return; 325 } 326 327 if (quick_format) 328 format_flag = SM_FORMAT_QUICK; 329 else if (long_format) 330 format_flag = SM_FORMAT_LONG; 331 else if (force_format) 332 format_flag = SM_FORMAT_FORCE; 333 334 if (med_info.sm_media_type == SM_FLOPPY) 335 format_flag = SM_FORMAT_HD; 336 337 if ((med_info.sm_media_type != SM_FLOPPY) && 338 (med_info.sm_media_type != SM_PCMCIA_MEM) && 339 (med_info.sm_media_type != SM_SCSI_FLOPPY)) { 340 global_intr_msg = "Interrupting format may render the \ 341 medium useless"; 342 } else { 343 global_intr_msg = ""; 344 } 345 trap_SIGINT(); 346 347 if (smedia_format(handle, format_flag, SM_FORMAT_IMMEDIATE) != 0) { 348 if (errno == EINVAL) { 349 (void) fprintf(stderr, gettext("Format failed.\n")); 350 (void) fprintf(stderr, gettext("The medium may not \ 351 be compatible for format operation.\n")); 352 (void) fprintf(stderr, gettext("read/write surface \ 353 scan may be used to get the effect of formatting.\n")); 354 } else { 355 PERROR("Format failed"); 356 } 357 (void) smedia_release_handle(handle); 358 (void) close(fd); 359 exit(1); 360 } 361 362 /* CONSTCOND */ 363 while (1) { 364 ret_val = smedia_check_format_status(handle); 365 if (ret_val == -1) { 366 if (errno != ENOTSUP) { 367 PERROR("Format failed"); 368 (void) smedia_release_handle(handle); 369 (void) close(fd); 370 exit(1); 371 } else { 372 /* Background formatting is not supported */ 373 break; 374 } 375 } 376 if (ret_val == 100) { 377 (void) printf("\n"); 378 (void) fflush(stdout); 379 break; 380 } 381 new_per = (ret_val * 80)/100; 382 while (new_per >= old_per) { 383 (void) printf("."); 384 (void) fflush(stdout); 385 old_per++; 386 } 387 (void) sleep(6); 388 } 389 390 if ((med_info.sm_media_type == SM_FLOPPY) || 391 (med_info.sm_media_type == SM_PCMCIA_MEM) || 392 (med_info.sm_media_type == SM_SCSI_FLOPPY)) { 393 (void) write_sunos_label(fd, med_info.sm_media_type); 394 } else { 395 396 /* 397 * Iomega drives don't destroy the data in quick format. 398 * Do a best effort write to first 1024 sectors. 399 */ 400 401 if (quick_format) 402 overwrite_metadata(fd, handle); 403 404 (void) write_default_label(handle, fd); 405 } 406 407 release_SIGINT(); 408 } 409 410 /* 411 * List removable devices. 412 */ 413 static void 414 process_l_flag() 415 { 416 int retry; 417 int removable; 418 int total_devices_found_last_time; 419 int defer = 0; 420 char *tmpstr = NULL; 421 422 #define MAX_RETRIES_FOR_SCANNING 3 423 424 vol_running = volmgt_running(); 425 if (vol_running) 426 defer = 1; 427 (void) printf(gettext("Looking for devices...\n")); 428 total_devices_found_last_time = 0; 429 430 /* 431 * Strip out any leading path. For example, /dev/rdsk/c3t0d0s2 432 * will result in tmpstr = c3t0d0s2. dev_name is given as input 433 * argument. 434 */ 435 if (dev_name) { 436 if ((tmpstr = strrchr(dev_name, '/')) != NULL) { 437 tmpstr += sizeof (char); 438 } else { 439 tmpstr = dev_name; 440 } 441 } 442 443 for (retry = 0; retry < MAX_RETRIES_FOR_SCANNING; retry++) { 444 removable = find_device(defer, tmpstr); 445 if (removable == -1) 446 break; 447 448 /* 449 * We'll do a small sleep and retry the command if volume 450 * manager is running and no removable devices are found. 451 * This is because the device may be busy. 452 */ 453 if (defer || (vol_running && (removable == 0))) { 454 if ((total_devices_found == 0) || 455 (total_devices_found != 456 total_devices_found_last_time)) { 457 total_devices_found_last_time = 458 total_devices_found; 459 (void) sleep(2); 460 } else { 461 /* Do the printing this time */ 462 defer = 0; 463 removable_found = 0; 464 } 465 466 } else 467 break; 468 } 469 if (removable_found == 0) 470 (void) printf(gettext("No removables found.\n")); 471 } 472 473 /* 474 * The following three routines handle the write protect 475 * options. These options are mostly Iomega ZIP/Jaz centric. 476 * The following options are allowed : 477 * No write protect <=> write protect without passwd : use -w flag 478 * from any state to WP with passwd : use -W flag 479 * from WP with passwd to no write protect : use -W flag 480 * from any state to RWP with passwd : use -R flag 481 * from RWP with passwd to no write protect : use -R flag 482 * 483 * The following transitions is not allowed 484 * WP with passwd or RWP to WP without passwd. 485 */ 486 487 static void 488 process_w_flag(smedia_handle_t handle) 489 { 490 int32_t rval; 491 int32_t med_status; 492 struct smwp_state wps; 493 494 if ((rval = smedia_get_protection_status((handle), &wps)) < 0) { 495 (void) fprintf(stderr, 496 gettext("Could not get medium status \n")); 497 return; 498 } 499 med_status = wps.sm_new_state; 500 501 wps.sm_version = SMWP_STATE_V_1; 502 503 if (wp_enable) { /* Enable write protect no password */ 504 505 switch (med_status) { 506 case SM_WRITE_PROTECT_DISABLE : 507 wps.sm_new_state = 508 SM_WRITE_PROTECT_NOPASSWD; 509 wps.sm_passwd_len = 0; 510 rval = smedia_set_protection_status(handle, 511 &wps); 512 if (rval == -1) 513 PERROR(WP_ERROR); 514 break; 515 case SM_WRITE_PROTECT_NOPASSWD : 516 (void) fprintf(stderr, gettext(WP_MSG_0)); 517 break; 518 case SM_WRITE_PROTECT_PASSWD : 519 (void) fprintf(stderr, gettext(WP_MSG_1)); 520 break; 521 case SM_READ_WRITE_PROTECT : 522 (void) fprintf(stderr, gettext(WP_MSG_2)); 523 break; 524 case SM_STATUS_UNKNOWN : 525 default : 526 (void) fprintf(stderr, gettext(WP_UNKNOWN)); 527 break; 528 } 529 } else if (wp_disable) { 530 switch (med_status) { 531 case SM_WRITE_PROTECT_NOPASSWD : 532 wps.sm_new_state = 533 SM_WRITE_PROTECT_DISABLE; 534 wps.sm_passwd_len = 0; 535 rval = smedia_set_protection_status(handle, 536 &wps); 537 if (rval == -1) 538 PERROR(WP_ERROR); 539 break; 540 case SM_WRITE_PROTECT_DISABLE : 541 (void) fprintf(stderr, gettext(WP_MSG_3)); 542 break; 543 case SM_WRITE_PROTECT_PASSWD : 544 (void) fprintf(stderr, gettext(WP_MSG_1)); 545 break; 546 case SM_READ_WRITE_PROTECT : 547 (void) fprintf(stderr, gettext(WP_MSG_2)); 548 break; 549 case SM_STATUS_UNKNOWN : 550 default : 551 (void) fprintf(stderr, gettext(WP_UNKNOWN)); 552 break; 553 } 554 } 555 } 556 557 static void 558 process_W_flag(smedia_handle_t handle) 559 { 560 int32_t rval; 561 int32_t med_status; 562 struct smwp_state wps; 563 564 DPRINTF("Write protect with password\n"); 565 566 if ((rval = smedia_get_protection_status((handle), &wps)) < 0) { 567 (void) fprintf(stderr, 568 gettext("Could not get medium status \n")); 569 return; 570 } 571 med_status = wps.sm_new_state; 572 573 wps.sm_version = SMWP_STATE_V_1; 574 575 if (wp_enable_passwd) { /* Enable write protect */ 576 switch (med_status) { 577 case SM_WRITE_PROTECT_DISABLE : 578 case SM_WRITE_PROTECT_NOPASSWD : 579 DPRINTF("Getting passwd\n"); 580 get_passwd(&wps, 1); 581 wps.sm_new_state = 582 SM_WRITE_PROTECT_PASSWD; 583 rval = smedia_set_protection_status(handle, 584 &wps); 585 if (rval == -1) { 586 PERROR(WP_ERROR); 587 } 588 break; 589 case SM_READ_WRITE_PROTECT : 590 (void) fprintf(stderr, gettext(WP_MSG_4)); 591 (void) fprintf(stderr, gettext(WP_MSG_5)); 592 get_passwd(&wps, 0); 593 wps.sm_new_state = 594 SM_WRITE_PROTECT_PASSWD; 595 rval = smedia_set_protection_status(handle, 596 &wps); 597 if (rval == -1) { 598 if (errno == EACCES) { 599 (void) fprintf(stderr, 600 gettext(WP_MSG_10)); 601 } else { 602 PERROR(WP_ERROR); 603 } 604 } 605 break; 606 case SM_WRITE_PROTECT_PASSWD : 607 (void) fprintf(stderr, gettext(WP_MSG_6)); 608 break; 609 case SM_STATUS_UNKNOWN : 610 default : 611 (void) fprintf(stderr, 612 gettext(WP_UNKNOWN)); 613 break; 614 } 615 } else if (wp_disable_passwd) { 616 switch (med_status) { 617 case SM_WRITE_PROTECT_PASSWD : 618 get_passwd(&wps, 0); 619 wps.sm_new_state = 620 SM_WRITE_PROTECT_DISABLE; 621 rval = smedia_set_protection_status(handle, 622 &wps); 623 if (rval == -1) { 624 if (errno == EACCES) { 625 (void) fprintf(stderr, 626 gettext(WP_MSG_10)); 627 } else { 628 PERROR(WP_ERROR); 629 } 630 } 631 break; 632 case SM_READ_WRITE_PROTECT : 633 (void) fprintf(stderr, gettext(WP_MSG_2)); 634 break; 635 case SM_WRITE_PROTECT_NOPASSWD : 636 (void) fprintf(stderr, gettext(WP_MSG_7)); 637 break; 638 case SM_WRITE_PROTECT_DISABLE : 639 (void) fprintf(stderr, gettext(WP_MSG_3)); 640 break; 641 case SM_STATUS_UNKNOWN : 642 default : 643 (void) fprintf(stderr, gettext(WP_UNKNOWN)); 644 break; 645 } 646 } 647 } 648 649 static void 650 process_R_flag(smedia_handle_t handle) 651 { 652 int32_t rval; 653 int32_t med_status; 654 struct smwp_state wps; 655 656 DPRINTF("Read Write protect \n"); 657 658 if ((rval = smedia_get_protection_status((handle), &wps)) < 0) { 659 (void) fprintf(stderr, 660 gettext("Could not get medium status \n")); 661 return; 662 } 663 med_status = wps.sm_new_state; 664 665 wps.sm_version = SMWP_STATE_V_1; 666 667 if (rw_protect_enable) { /* Enable write protect */ 668 switch (med_status) { 669 case SM_WRITE_PROTECT_DISABLE : 670 case SM_WRITE_PROTECT_NOPASSWD : 671 DPRINTF("Getting passwd\n"); 672 get_passwd(&wps, 1); 673 wps.sm_new_state = 674 SM_READ_WRITE_PROTECT; 675 rval = smedia_set_protection_status(handle, 676 &wps); 677 if (rval == -1) 678 PERROR(WP_ERROR); 679 break; 680 case SM_WRITE_PROTECT_PASSWD : 681 (void) fprintf(stderr, gettext(WP_MSG_8)); 682 (void) fprintf(stderr, gettext(WP_MSG_9)); 683 get_passwd(&wps, 0); 684 wps.sm_new_state = 685 SM_READ_WRITE_PROTECT; 686 rval = smedia_set_protection_status(handle, 687 &wps); 688 if (rval == -1) { 689 if (errno == EACCES) { 690 (void) fprintf(stderr, 691 gettext(WP_MSG_10)); 692 } else { 693 PERROR(WP_ERROR); 694 } 695 } 696 break; 697 case SM_READ_WRITE_PROTECT : 698 (void) fprintf(stderr, gettext(WP_MSG_4)); 699 break; 700 case SM_STATUS_UNKNOWN : 701 default : 702 (void) fprintf(stderr, gettext(WP_UNKNOWN)); 703 break; 704 } 705 } else if (rw_protect_disable) { 706 switch (med_status) { 707 case SM_READ_WRITE_PROTECT : 708 case SM_STATUS_UNKNOWN : 709 get_passwd(&wps, 0); 710 wps.sm_new_state = 711 SM_WRITE_PROTECT_DISABLE; 712 rval = smedia_set_protection_status(handle, 713 &wps); 714 if (rval == -1) { 715 if (errno == EACCES) { 716 (void) fprintf(stderr, 717 gettext(WP_MSG_10)); 718 } else { 719 PERROR(WP_ERROR); 720 } 721 } 722 break; 723 case SM_WRITE_PROTECT_PASSWD : 724 (void) fprintf(stderr, gettext(WP_MSG_1)); 725 break; 726 case SM_WRITE_PROTECT_NOPASSWD : 727 (void) fprintf(stderr, gettext(WP_MSG_7)); 728 break; 729 case SM_WRITE_PROTECT_DISABLE : 730 (void) fprintf(stderr, gettext(WP_MSG_3)); 731 break; 732 default : 733 (void) fprintf(stderr, gettext(WP_UNKNOWN)); 734 break; 735 } 736 } 737 } 738 739 void 740 process_p_flag(smedia_handle_t handle, int32_t fd) 741 { 742 int32_t med_status; 743 smwp_state_t wps; 744 745 med_status = smedia_get_protection_status((handle), &wps); 746 DPRINTF("Could not get medium status \n"); 747 748 /* 749 * Workaround in case mode sense fails. 750 * 751 * Also, special handling for PCMCIA. PCMCIA does not have any 752 * ioctl to find out the write protect status. So, open the 753 * device with O_RDWR. If it passes, it is not write protected, 754 * otherwise it is write protected. 755 * If it fails, reopen with O_RDONLY, may be some other 756 * operation can go through. 757 */ 758 if ((med_status < 0) || (med_info.sm_media_type == SM_PCMCIA_MEM) || 759 (med_info.sm_media_type == SM_PCMCIA_ATA)) { 760 (void) close(fd); 761 DPRINTF("Reopening device for -p option\n"); 762 fd = my_open(dev_name, O_RDONLY|O_NDELAY); 763 if (fd < 0) { 764 if (p_flag) { 765 PERROR("Could not open device"); 766 (void) smedia_release_handle(handle); 767 (void) close(fd); 768 exit(1); 769 } else { 770 (void) fprintf(stdout, 771 gettext("<Unknown>\n")); 772 (void) smedia_release_handle(handle); 773 (void) close(fd); 774 return; 775 } 776 fd = my_open(dev_name, O_RDWR|O_NDELAY); 777 if (fd < 0) { 778 (void) fprintf(stdout, 779 gettext("Medium is write protected.\n")); 780 } 781 } else { /* Open succeeded */ 782 (void) fprintf(stdout, 783 gettext("Medium is not write protected.\n")); 784 } 785 return; 786 } 787 med_status = wps.sm_new_state; 788 switch (med_status) { 789 790 case SM_READ_WRITE_PROTECT : 791 (void) fprintf(stdout, 792 gettext("Medium is read-write protected.\n")); 793 break; 794 case SM_WRITE_PROTECT_PASSWD : 795 (void) fprintf(stdout, 796 gettext("Medium is write protected with password.\n")); 797 break; 798 case SM_WRITE_PROTECT_NOPASSWD : 799 (void) fprintf(stdout, 800 gettext("Medium is write protected.\n")); 801 break; 802 case SM_WRITE_PROTECT_DISABLE : 803 (void) fprintf(stdout, 804 gettext("Medium is not write protected.\n")); 805 break; 806 case SM_STATUS_UNKNOWN : 807 default: 808 (void) fprintf(stdout, 809 gettext("Unknown write protect status.\n")); 810 break; 811 } 812 } 813 814 static void 815 process_c_flag(smedia_handle_t handle) 816 { 817 char error_string[256]; 818 819 if (smedia_reassign_block(handle, repair_blk_no) != 0) { 820 (void) snprintf(error_string, 255, 821 gettext("Could not repair block no %llu"), repair_blk_no); 822 PERROR(error_string); 823 return; 824 } 825 } 826 827 /* 828 * This routine handles the -V (verify) option. 829 * There can be devices without rw_read option. If the raw_read 830 * and raw_write are not supported by the interface, then read and 831 * write system calls are used. It is assumed that either both 832 * raw_read and raw_write are supported or both are unsupported. 833 */ 834 835 static void 836 process_V_flag(smedia_handle_t handle, int32_t fd) 837 { 838 int32_t ret; 839 uint32_t j; 840 diskaddr_t bn; 841 char *read_buf, *write_buf; 842 int32_t old_per = 0; 843 int32_t new_per; 844 int32_t no_raw_rw = 0; 845 int32_t verify_size; 846 diskaddr_t capacity; 847 int32_t blocksize; 848 849 DPRINTF("ANALYSE MEDIA \n"); 850 851 ret = smedia_get_medium_property(handle, &med_info); 852 if (ret == -1) { 853 DPRINTF("get_media_info failed\n"); 854 return; 855 } 856 857 DPRINTF1("media_type %d\n", med_info.sm_media_type); 858 DPRINTF1("sector_size %d\n", med_info.sm_blocksize); 859 DPRINTF1("num_sectors %u\n", (uint32_t)med_info.sm_capacity); 860 DPRINTF1("nsect %d\n", med_info.sm_nsect); 861 862 blocksize = med_info.sm_blocksize; 863 864 capacity = (uint32_t)med_info.sm_capacity; 865 verify_size = (med_info.sm_nsect > 64) ? 64 : med_info.sm_nsect; 866 read_buf = (char *)malloc(blocksize * verify_size); 867 if (read_buf == NULL) { 868 DPRINTF("Could not allocate memory\n"); 869 return; 870 } 871 write_buf = (char *)malloc(blocksize * verify_size); 872 if (write_buf == NULL) { 873 DPRINTF("Could not allocate memory\n"); 874 free(read_buf); 875 return; 876 } 877 878 if (!verify_write) { 879 DPRINTF("Non-destructive verify \n"); 880 for (bn = 0; bn < (uint32_t)med_info.sm_capacity; 881 bn += verify_size) { 882 new_per = (bn * 80)/(uint32_t)med_info.sm_capacity; 883 if (new_per >= old_per) { 884 (void) printf("."); 885 (void) fflush(stdout); 886 old_per++; 887 } 888 DPRINTF2("Reading %d blks starting at %llu\n", 889 verify_size, bn); 890 ret = verify(handle, fd, bn, verify_size, read_buf, 891 VERIFY_READ, blocksize, no_raw_rw); 892 if ((ret == -1) && (errno == ENOTSUP)) { 893 no_raw_rw = 1; 894 ret = verify(handle, fd, bn, verify_size, 895 read_buf, 896 VERIFY_READ, blocksize, no_raw_rw); 897 capacity = (diskaddr_t)med_info.sm_pcyl * 898 med_info.sm_nhead * med_info.sm_nsect; 899 } 900 901 if (ret != 0) { 902 for (j = 0; j < verify_size; j++) { 903 if ((bn + j) >= capacity) 904 return; 905 DPRINTF2( 906 "Reading %d blks starting " 907 "at %llu\n", 1, bn + j); 908 ret = verify(handle, fd, bn + j, 1, 909 read_buf, 910 VERIFY_READ, blocksize, 911 no_raw_rw); 912 if (ret == -1) { 913 (void) printf( 914 "Bad block %llu\n", 915 bn + j); 916 } 917 } 918 } 919 } 920 } else { 921 922 DPRINTF("Destrutive verify \n"); 923 for (bn = 0; bn < (uint32_t)med_info.sm_capacity; 924 bn += verify_size) { 925 new_per = (bn * 80)/(uint32_t)med_info.sm_capacity; 926 if (new_per >= old_per) { 927 (void) printf("."); 928 929 (void) fflush(stdout); 930 old_per++; 931 } 932 933 for (j = 0; j < blocksize * verify_size; j++) { 934 write_buf[j] = (bn | j) & 0xFF; 935 } 936 DPRINTF2("Writing %d blks starting at %llu\n", 937 verify_size, bn); 938 ret = verify(handle, fd, bn, verify_size, write_buf, 939 VERIFY_WRITE, blocksize, no_raw_rw); 940 941 if (ret != 0) { 942 for (j = 0; j < verify_size; j++) { 943 if ((bn + j) >= capacity) 944 break; 945 DPRINTF2( 946 "Writing %d blks starting " 947 "at %llu\n", 1, bn + j); 948 ret = verify(handle, fd, bn + j, 1, 949 write_buf, 950 VERIFY_WRITE, blocksize, 951 no_raw_rw); 952 if (ret == -1) { 953 (void) printf( 954 "Bad block %llu\n", bn + j); 955 } 956 } 957 } 958 DPRINTF2("Read after write %d blks starting at %llu\n", 959 verify_size, bn); 960 ret = verify(handle, fd, bn, verify_size, 961 read_buf, VERIFY_READ, blocksize, no_raw_rw); 962 963 if (ret != 0) { 964 for (j = 0; j < verify_size; j++) { 965 if ((bn + j) >= capacity) 966 return; 967 DPRINTF2( 968 "Read after write %d blks " 969 "starting at %llu\n", 1, bn + j); 970 ret = verify(handle, fd, bn + j, 1, 971 read_buf, VERIFY_READ, 972 blocksize, no_raw_rw); 973 if (ret == -1) { 974 (void) printf( 975 "Bad block %llu\n", bn + j); 976 } 977 } 978 } 979 980 981 } 982 } 983 } 984 985 static void 986 process_s_flag(smedia_handle_t handle, int32_t fd) 987 { 988 int32_t i, ret; 989 struct extvtoc v_toc, t_vtoc; 990 if (valid_slice_file(handle, fd, slice_file, &v_toc)) { 991 (void) smedia_release_handle(handle); 992 (void) close(fd); 993 exit(1); 994 } 995 996 (void) memset(&t_vtoc, 0, sizeof (t_vtoc)); 997 998 999 t_vtoc.v_nparts = V_NUMPAR; 1000 t_vtoc.v_sanity = VTOC_SANE; 1001 t_vtoc.v_version = V_VERSION; 1002 t_vtoc.v_sectorsz = DEV_BSIZE; 1003 1004 /* Get existing Vtoc, don't bother if it fails. */ 1005 1006 /* Turn on privileges. */ 1007 (void) __priv_bracket(PRIV_ON); 1008 1009 (void) read_extvtoc(fd, &t_vtoc); 1010 1011 /* Turn off privileges. */ 1012 (void) __priv_bracket(PRIV_OFF); 1013 1014 for (i = 0; i < V_NUMPAR; i++) { 1015 t_vtoc.v_part[i].p_start = v_toc.v_part[i].p_start; 1016 t_vtoc.v_part[i].p_size = v_toc.v_part[i].p_size; 1017 t_vtoc.v_part[i].p_tag = v_toc.v_part[i].p_tag; 1018 t_vtoc.v_part[i].p_flag = v_toc.v_part[i].p_flag; 1019 } 1020 1021 errno = 0; 1022 1023 1024 /* Turn on privileges. */ 1025 (void) __priv_bracket(PRIV_ON); 1026 1027 ret = write_extvtoc(fd, &t_vtoc); 1028 1029 /* Turn off privileges. */ 1030 (void) __priv_bracket(PRIV_OFF); 1031 1032 if (ret < 0) { 1033 #ifdef sparc 1034 PERROR("write VTOC failed"); 1035 DPRINTF1("Errno = %d\n", errno); 1036 #else /* i386 */ 1037 if (errno == EIO) { 1038 PERROR("No Solaris partition, eject & retry"); 1039 DPRINTF1("Errno = %d\n", errno); 1040 } else { 1041 PERROR("write VTOC failed"); 1042 DPRINTF1("Errno = %d\n", errno); 1043 } 1044 #endif 1045 } 1046 } 1047 static void 1048 process_e_flag(smedia_handle_t handle) 1049 { 1050 if (smedia_eject(handle) < 0) { 1051 PERROR("Eject failed"); 1052 } 1053 } 1054 static void 1055 process_H_flag(smedia_handle_t handle, int32_t fd) 1056 { 1057 uint32_t cyl, head; 1058 int32_t old_per = 0; 1059 int32_t new_per; 1060 1061 (void) fprintf(stderr, 1062 gettext("Formatting will erase all the data on disk.\n")); 1063 if (!get_confirmation()) 1064 return; 1065 1066 for (cyl = 0; cyl < med_info.sm_pcyl; cyl++) { 1067 for (head = 0; head < med_info.sm_nhead; head++) { 1068 if (smedia_format_track(handle, cyl, head, SM_FORMAT_HD) 1069 < 0) { 1070 PERROR("Format failed"); 1071 return; 1072 } 1073 } 1074 new_per = (cyl * 80)/med_info.sm_pcyl; 1075 while (new_per >= old_per) { 1076 (void) printf("."); 1077 (void) fflush(stdout); 1078 old_per++; 1079 } 1080 } 1081 1082 (void) write_sunos_label(fd, med_info.sm_media_type); 1083 } 1084 1085 static void 1086 process_D_flag(smedia_handle_t handle, int32_t fd) 1087 { 1088 uint32_t cyl, head; 1089 int32_t old_per = 0; 1090 int32_t new_per; 1091 1092 (void) fprintf(stderr, 1093 gettext("Formatting will erase all the data on disk.\n")); 1094 if (!get_confirmation()) 1095 return; 1096 for (cyl = 0; cyl < med_info.sm_pcyl; cyl++) { 1097 for (head = 0; head < med_info.sm_nhead; head++) { 1098 if (smedia_format_track(handle, cyl, head, SM_FORMAT_DD) 1099 < 0) { 1100 PERROR("Format failed"); 1101 return; 1102 } 1103 } 1104 new_per = (cyl * 80)/med_info.sm_pcyl; 1105 while (new_per >= old_per) { 1106 (void) printf("."); 1107 (void) fflush(stdout); 1108 old_per++; 1109 } 1110 } 1111 (void) write_sunos_label(fd, med_info.sm_media_type); 1112 } 1113 1114 /* 1115 * This routine handles the -b (label) option. 1116 * Please note that, this will fail if there is no valid vtoc is 1117 * there on the medium and the vtoc is not faked. 1118 */ 1119 1120 static void 1121 process_b_flag(int32_t fd) 1122 { 1123 int32_t ret, nparts; 1124 struct extvtoc v_toc; 1125 struct dk_gpt *vtoc64; 1126 1127 /* For EFI disks. */ 1128 if (efi_type(fd)) { 1129 if (efi_alloc_and_read(fd, &vtoc64) < 0) { 1130 /* 1131 * If reading the vtoc failed, try to 1132 * auto-sense the disk configuration. 1133 */ 1134 if (efi_auto_sense(fd, &vtoc64) < 0) { 1135 (void) fprintf(stderr, 1136 gettext("Could not write label.\n")); 1137 return; 1138 } 1139 } 1140 for (nparts = 0; nparts < vtoc64->efi_nparts; 1141 nparts++) { 1142 if (vtoc64->efi_parts[nparts].p_tag == 1143 V_RESERVED) { 1144 if (vtoc64->efi_parts[nparts].p_name) { 1145 (void) strncpy( 1146 vtoc64->efi_parts[nparts].p_name, label, 1147 EFI_PART_NAME_LEN); 1148 } 1149 break; 1150 } 1151 } 1152 if (efi_write(fd, vtoc64) != 0) { 1153 (void) efi_err_check(vtoc64); 1154 (void) fprintf(stderr, 1155 gettext("Could not write label.\n")); 1156 } 1157 return; 1158 } 1159 1160 /* Get existing Vtoc */ 1161 1162 /* Turn on privileges. */ 1163 (void) __priv_bracket(PRIV_ON); 1164 1165 ret = read_extvtoc(fd, &v_toc); 1166 1167 /* Turn off privileges */ 1168 (void) __priv_bracket(PRIV_OFF); 1169 1170 if (ret < 0) { 1171 #ifdef sparc 1172 PERROR("read VTOC failed"); 1173 DPRINTF1("Errno = %d\n", errno); 1174 #else /* i386 */ 1175 if (errno == EIO) { 1176 PERROR("No Solaris partition, eject & retry"); 1177 DPRINTF1("Errno = %d\n", errno); 1178 } else { 1179 PERROR("read VTOC failed"); 1180 DPRINTF1("Errno = %d\n", errno); 1181 } 1182 #endif 1183 return; 1184 } 1185 1186 (void) strncpy(v_toc.v_volume, label, LEN_DKL_VVOL); 1187 1188 1189 /* Turn on the privileges. */ 1190 (void) __priv_bracket(PRIV_ON); 1191 1192 ret = write_extvtoc(fd, &v_toc); 1193 1194 /* Turn off the privileges. */ 1195 (void) __priv_bracket(PRIV_OFF); 1196 1197 if (ret < 0) { 1198 #ifdef sparc 1199 PERROR("write VTOC failed"); 1200 DPRINTF1("Errno = %d\n", errno); 1201 #else /* i386 */ 1202 if (errno == EIO) { 1203 PERROR("No Solaris partition, eject & retry"); 1204 DPRINTF1("Errno = %d\n", errno); 1205 } else { 1206 PERROR("write VTOC failed"); 1207 DPRINTF1("Errno = %d\n", errno); 1208 } 1209 #endif 1210 } 1211 }