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