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