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 }