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