xref: /illumos-gate/usr/src/cmd/rmformat/rmf_menu.c (revision 99f63845ee65f89a523460ce4b6b0603a06eceb7)
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 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
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 uint32_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 vtoc *);
79 extern void trap_SIGINT();
80 extern void release_SIGINT();
81 extern int32_t verify(smedia_handle_t handle, int32_t fd,
82 		uint32_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 %x\n", 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;
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;
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(stderr,
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(stderr,
779 				gettext("Medium is write protected.\n"));
780 			}
781 		} else { /* Open succeeded */
782 			(void) fprintf(stderr,
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(stderr,
792 			gettext("Medium is read-write protected.\n"));
793 			break;
794 		case SM_WRITE_PROTECT_PASSWD :
795 			(void) fprintf(stderr,
796 			gettext("Medium is write protected with password.\n"));
797 			break;
798 		case SM_WRITE_PROTECT_NOPASSWD :
799 			(void) fprintf(stderr,
800 			gettext("Medium is write protected.\n"));
801 			break;
802 		case SM_WRITE_PROTECT_DISABLE  :
803 			(void) fprintf(stderr,
804 			gettext("Medium is not write protected.\n"));
805 			break;
806 		case SM_STATUS_UNKNOWN :
807 			default:
808 			(void) fprintf(stderr,
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 %d"), 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 i, j;
840 	char *read_buf, *write_buf;
841 	int32_t old_per = 0;
842 	int32_t new_per;
843 	int32_t no_raw_rw = 0;
844 	int32_t verify_size;
845 	uint32_t capacity;
846 	int32_t blocksize;
847 
848 	DPRINTF("ANALYSE MEDIA \n");
849 
850 	ret = smedia_get_medium_property(handle, &med_info);
851 	if (ret == -1) {
852 		DPRINTF("get_media_info failed\n");
853 		return;
854 	}
855 
856 	DPRINTF1("media_type %d\n", med_info.sm_media_type);
857 	DPRINTF1("sector_size %d\n", med_info.sm_blocksize);
858 	DPRINTF1("num_sectors %d\n", med_info.sm_capacity);
859 	DPRINTF1("nsect	 %d\n", med_info.sm_nsect);
860 
861 	blocksize = med_info.sm_blocksize;
862 
863 	capacity = med_info.sm_capacity;
864 	verify_size = (med_info.sm_nsect > 64) ? 64 : med_info.sm_nsect;
865 	read_buf = (char *)malloc(blocksize * verify_size);
866 	if (read_buf == NULL) {
867 		DPRINTF("Could not allocate memory\n");
868 		return;
869 	}
870 	write_buf = (char *)malloc(blocksize * verify_size);
871 	if (write_buf == NULL) {
872 		DPRINTF("Could not allocate memory\n");
873 		free(read_buf);
874 		return;
875 	}
876 
877 	if (!verify_write) {
878 		DPRINTF("Non-destructive verify \n");
879 		for (i = 0; i < med_info.sm_capacity; i += verify_size) {
880 			new_per = (i * 80)/med_info.sm_capacity;
881 			if (new_per >= old_per) {
882 				(void) printf(".");
883 				(void) fflush(stdout);
884 				old_per++;
885 			}
886 			DPRINTF2("Reading %d blks starting at %d\n",
887 				verify_size, i);
888 			ret = verify(handle, fd, i, verify_size, read_buf,
889 				VERIFY_READ, blocksize, no_raw_rw);
890 			if ((ret == -1) && (errno == ENOTSUP)) {
891 				no_raw_rw = 1;
892 				ret = verify(handle, fd, i, verify_size,
893 					read_buf,
894 					VERIFY_READ, blocksize, no_raw_rw);
895 				capacity = med_info.sm_pcyl * med_info.sm_nhead
896 					* med_info.sm_nsect;
897 			}
898 
899 			if (ret != 0) {
900 				for (j = 0; j < verify_size; j++) {
901 					if ((i + j) >= capacity)
902 							return;
903 					    DPRINTF2(
904 					"Reading %d blks starting at %d\n",
905 						1, i+j);
906 					ret = verify(handle, fd, i + j, 1,
907 						read_buf,
908 						VERIFY_READ, blocksize,
909 						no_raw_rw);
910 					if (ret == -1) {
911 						(void) printf("Bad block %d\n",
912 							i+j);
913 					}
914 				}
915 			}
916 		}
917 	} else {
918 
919 		DPRINTF("Destrutive verify \n");
920 		for (i = 0; i < med_info.sm_capacity; i += verify_size) {
921 			new_per = (i * 80)/med_info.sm_capacity;
922 			if (new_per >= old_per) {
923 				(void) printf(".");
924 
925 				(void) fflush(stdout);
926 				old_per++;
927 			}
928 
929 			for (j = 0; j < blocksize * verify_size; j++) {
930 				write_buf[j] = (i|j) & 0xFF;
931 			}
932 			DPRINTF2("Writing %d blks starting at %d\n",
933 				verify_size, i);
934 			ret = verify(handle, fd, i, verify_size, write_buf,
935 				VERIFY_WRITE, blocksize, no_raw_rw);
936 
937 			if (ret != 0) {
938 				for (j = 0; j < verify_size; j++) {
939 					if ((i + j) >= capacity)
940 							break;
941 					DPRINTF2(
942 				"Writing %d blks starting at %d\n",
943 					1, i+j);
944 					ret = verify(handle, fd, i + j, 1,
945 						write_buf,
946 						VERIFY_WRITE, blocksize,
947 						no_raw_rw);
948 					if (ret == -1) {
949 						(void) printf("Bad block %d\n",
950 							i+j);
951 					}
952 				}
953 			}
954 			DPRINTF2("Read after write  %d blks starting at %d\n",
955 				verify_size, i);
956 			ret = verify(handle, fd, i, verify_size,
957 				read_buf, VERIFY_READ, blocksize, no_raw_rw);
958 
959 			if (ret != 0) {
960 				for (j = 0; j < verify_size; j++) {
961 					if ((i + j) >= capacity)
962 							return;
963 					DPRINTF2(
964 				"Read after write  %d blks starting at %d\n",
965 					1, i+j);
966 					ret = verify(handle, fd, i + j, 1,
967 						read_buf, VERIFY_READ,
968 						blocksize, no_raw_rw);
969 					if (ret == -1) {
970 						(void) printf("Bad block %d\n",
971 							i+j);
972 					}
973 				}
974 			}
975 
976 
977 		}
978 	}
979 }
980 
981 static void
982 process_s_flag(smedia_handle_t handle, int32_t fd)
983 {
984 	int32_t i, ret;
985 	struct vtoc v_toc, t_vtoc;
986 	if (valid_slice_file(handle, fd, slice_file, &v_toc)) {
987 			(void) smedia_release_handle(handle);
988 			(void) close(fd);
989 			exit(1);
990 	}
991 
992 	(void) memset(&t_vtoc, 0, sizeof (t_vtoc));
993 
994 
995 	t_vtoc.v_nparts = V_NUMPAR;
996 	t_vtoc.v_sanity = VTOC_SANE;
997 	t_vtoc.v_version = V_VERSION;
998 	t_vtoc.v_sectorsz = DEV_BSIZE;
999 
1000 	/* Get existing Vtoc, don't bother if it fails. */
1001 
1002 	/* Turn on privileges. */
1003 	(void) __priv_bracket(PRIV_ON);
1004 
1005 	(void) read_vtoc(fd, &t_vtoc);
1006 
1007 	/* Turn off privileges. */
1008 	(void) __priv_bracket(PRIV_OFF);
1009 
1010 	for (i = 0; i < V_NUMPAR; i++) {
1011 		t_vtoc.v_part[i].p_start = v_toc.v_part[i].p_start;
1012 		t_vtoc.v_part[i].p_size = v_toc.v_part[i].p_size;
1013 		t_vtoc.v_part[i].p_tag	= v_toc.v_part[i].p_tag;
1014 		t_vtoc.v_part[i].p_flag = v_toc.v_part[i].p_flag;
1015 	}
1016 
1017 	errno = 0;
1018 
1019 
1020 	/* Turn on privileges. */
1021 	(void) __priv_bracket(PRIV_ON);
1022 
1023 	ret = write_vtoc(fd, &t_vtoc);
1024 
1025 	/* Turn off privileges. */
1026 	(void) __priv_bracket(PRIV_OFF);
1027 
1028 	if (ret < 0)  {
1029 #ifdef sparc
1030 		PERROR("write VTOC failed");
1031 		DPRINTF1("Errno = %d\n", errno);
1032 #else /* i386 */
1033 		if (errno == EIO) {
1034 			PERROR("No Solaris partition, eject & retry");
1035 			DPRINTF1("Errno = %d\n", errno);
1036 		} else {
1037 			PERROR("write VTOC failed");
1038 			DPRINTF1("Errno = %d\n", errno);
1039 		}
1040 #endif
1041 	}
1042 }
1043 static void
1044 process_e_flag(smedia_handle_t handle)
1045 {
1046 	if (smedia_eject(handle) < 0) {
1047 		PERROR("Eject failed");
1048 	}
1049 }
1050 static void
1051 process_H_flag(smedia_handle_t handle, int32_t fd)
1052 {
1053 	uint32_t cyl, head;
1054 	int32_t old_per = 0;
1055 	int32_t new_per;
1056 
1057 	(void) fprintf(stderr,
1058 		gettext("Formatting will erase all the data on disk.\n"));
1059 	if (!get_confirmation())
1060 		return;
1061 
1062 	for (cyl = 0; cyl < med_info.sm_pcyl; cyl++) {
1063 		for (head = 0; head < med_info.sm_nhead; head++) {
1064 			if (smedia_format_track(handle, cyl, head, SM_FORMAT_HD)
1065 									< 0) {
1066 					PERROR("Format failed");
1067 					return;
1068 			}
1069 		}
1070 		new_per = (cyl * 80)/med_info.sm_pcyl;
1071 		while (new_per >= old_per) {
1072 			(void) printf(".");
1073 			(void) fflush(stdout);
1074 			old_per++;
1075 		}
1076 	}
1077 
1078 	(void) write_sunos_label(fd, med_info.sm_media_type);
1079 }
1080 
1081 static void
1082 process_D_flag(smedia_handle_t handle, int32_t fd)
1083 {
1084 	uint32_t cyl, head;
1085 	int32_t old_per = 0;
1086 	int32_t new_per;
1087 
1088 	(void) fprintf(stderr,
1089 		gettext("Formatting will erase all the data on disk.\n"));
1090 	if (!get_confirmation())
1091 		return;
1092 	for (cyl = 0; cyl < med_info.sm_pcyl; cyl++) {
1093 		for (head = 0; head < med_info.sm_nhead; head++) {
1094 			if (smedia_format_track(handle, cyl, head, SM_FORMAT_DD)
1095 									< 0) {
1096 					PERROR("Format failed");
1097 					return;
1098 			}
1099 		}
1100 		new_per = (cyl * 80)/med_info.sm_pcyl;
1101 		while (new_per >= old_per) {
1102 			(void) printf(".");
1103 			(void) fflush(stdout);
1104 			old_per++;
1105 		}
1106 	}
1107 	(void) write_sunos_label(fd, med_info.sm_media_type);
1108 }
1109 
1110 /*
1111  * This routine handles the -b (label) option.
1112  * Please note that, this will fail if there is no valid vtoc is
1113  * there on the medium and the vtoc is not faked.
1114  */
1115 
1116 static void
1117 process_b_flag(int32_t fd)
1118 {
1119 	int32_t ret, nparts;
1120 	struct vtoc v_toc;
1121 	struct dk_gpt *vtoc64;
1122 
1123 	/* For EFI disks. */
1124 	if (efi_type(fd)) {
1125 		if (efi_alloc_and_read(fd, &vtoc64) < 0) {
1126 			/*
1127 			 * If reading the vtoc failed, try to
1128 			 * auto-sense the disk configuration.
1129 			 */
1130 			if (efi_auto_sense(fd, &vtoc64) < 0) {
1131 				(void) fprintf(stderr,
1132 				    gettext("Could not write label.\n"));
1133 				return;
1134 			}
1135 		}
1136 		for (nparts = 0; nparts < vtoc64->efi_nparts;
1137 			nparts++) {
1138 		    if (vtoc64->efi_parts[nparts].p_tag ==
1139 			V_RESERVED) {
1140 			if (vtoc64->efi_parts[nparts].p_name) {
1141 				(void) strncpy(
1142 				    vtoc64->efi_parts[nparts].p_name, label,
1143 				    EFI_PART_NAME_LEN);
1144 			}
1145 			break;
1146 		    }
1147 		}
1148 		if (efi_write(fd, vtoc64) != 0) {
1149 			(void) efi_err_check(vtoc64);
1150 			(void) fprintf(stderr,
1151 				    gettext("Could not write label.\n"));
1152 		}
1153 		return;
1154 	}
1155 
1156 	/* Get existing Vtoc */
1157 
1158 	/* Turn on privileges. */
1159 	(void) __priv_bracket(PRIV_ON);
1160 
1161 	ret = read_vtoc(fd, &v_toc);
1162 
1163 	/* Turn off privileges */
1164 	(void) __priv_bracket(PRIV_OFF);
1165 
1166 	if (ret < 0) {
1167 #ifdef sparc
1168 		PERROR("read VTOC failed");
1169 		DPRINTF1("Errno = %d\n", errno);
1170 #else /* i386 */
1171 		if (errno == EIO) {
1172 			PERROR("No Solaris partition, eject & retry");
1173 			DPRINTF1("Errno = %d\n", errno);
1174 		} else {
1175 			PERROR("read VTOC failed");
1176 			DPRINTF1("Errno = %d\n", errno);
1177 		}
1178 #endif
1179 		return;
1180 	}
1181 
1182 	(void) strncpy(v_toc.v_volume, label, LEN_DKL_VVOL);
1183 
1184 
1185 	/* Turn on the privileges. */
1186 	(void) __priv_bracket(PRIV_ON);
1187 
1188 	ret = write_vtoc(fd, &v_toc);
1189 
1190 	/* Turn off the privileges. */
1191 	(void) __priv_bracket(PRIV_OFF);
1192 
1193 	if (ret < 0) {
1194 #ifdef sparc
1195 		PERROR("write VTOC failed");
1196 		DPRINTF1("Errno = %d\n", errno);
1197 #else /* i386 */
1198 		if (errno == EIO) {
1199 			PERROR("No Solaris partition, eject & retry");
1200 			DPRINTF1("Errno = %d\n", errno);
1201 		} else {
1202 			PERROR("write VTOC failed");
1203 			DPRINTF1("Errno = %d\n", errno);
1204 		}
1205 #endif
1206 	}
1207 }
1208