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