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