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 }