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