xref: /onnv-gate/usr/src/cmd/rmformat/rmf_misc.c (revision 11215:821b7edb881c)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52160Szk194757  * Common Development and Distribution License (the "License").
62160Szk194757  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
217563SPrasad.Singamsetty@Sun.COM 
220Sstevel@tonic-gate /*
23*9525SPavel.Potoplyak@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate  * rmf_misc.c :
290Sstevel@tonic-gate  *	Miscelleneous routines for rmformat.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <sys/mnttab.h>
350Sstevel@tonic-gate #include <volmgt.h>
360Sstevel@tonic-gate #include <sys/dkio.h>
370Sstevel@tonic-gate #include <sys/fdio.h>
380Sstevel@tonic-gate #include <sys/vtoc.h>
390Sstevel@tonic-gate #include <sys/termios.h>
400Sstevel@tonic-gate #include <sys/mount.h>
410Sstevel@tonic-gate #include <ctype.h>
420Sstevel@tonic-gate #include <signal.h>
430Sstevel@tonic-gate #include <sys/wait.h>
440Sstevel@tonic-gate #include <dirent.h>
452172Szk194757 #include <priv_utils.h>
460Sstevel@tonic-gate #include <stdarg.h>
470Sstevel@tonic-gate #include "rmformat.h"
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * Definitions.
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate #define	SENSE_KEY(rqbuf)	(rqbuf[2] & 0xf) /* scsi error category */
530Sstevel@tonic-gate #define	ASC(rqbuf)		(rqbuf[12])	/* additional sense code */
540Sstevel@tonic-gate #define	ASCQ(rqbuf)		(rqbuf[13])	/* ASC qualifier */
550Sstevel@tonic-gate 
560Sstevel@tonic-gate #define	DEFAULT_SCSI_TIMEOUT	60
570Sstevel@tonic-gate #define	INQUIRY_CMD		0x12
580Sstevel@tonic-gate #define	RQBUFLEN		32
590Sstevel@tonic-gate #define	CD_RW			1		/* CD_RW/CD-R	*/
600Sstevel@tonic-gate #define	WRITE_10_CMD		0x2A
610Sstevel@tonic-gate #define	READ_INFO_CMD		0x51
620Sstevel@tonic-gate #define	SYNC_CACHE_CMD		0x35
630Sstevel@tonic-gate #define	CLOSE_TRACK_CMD 	0x5B
640Sstevel@tonic-gate #define	MODE_SENSE_10_CMD	0x5A
650Sstevel@tonic-gate #define	DEVFS_PREFIX		"/devices"
660Sstevel@tonic-gate 
670Sstevel@tonic-gate int		uscsi_error;		 /* used for debugging failed uscsi */
680Sstevel@tonic-gate char		rqbuf[RQBUFLEN];
690Sstevel@tonic-gate static uint_t	total_retries;
700Sstevel@tonic-gate static struct	uscsi_cmd uscmd;
710Sstevel@tonic-gate static char	ucdb[16];
720Sstevel@tonic-gate uchar_t 	uscsi_status, rqstatus, rqresid;
730Sstevel@tonic-gate int		total_devices_found = 0;
740Sstevel@tonic-gate int		removable_found = 0;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate extern char	*global_intr_msg;
770Sstevel@tonic-gate extern int	vol_running;
780Sstevel@tonic-gate extern char	*dev_name;
790Sstevel@tonic-gate extern int32_t	m_flag;
800Sstevel@tonic-gate 
810Sstevel@tonic-gate /*
820Sstevel@tonic-gate  * ON-private functions from libvolmgt
830Sstevel@tonic-gate  */
840Sstevel@tonic-gate int	_dev_mounted(char *path);
850Sstevel@tonic-gate 
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate  * Function prototypes.
880Sstevel@tonic-gate  */
890Sstevel@tonic-gate static int		my_umount(char *mountp);
900Sstevel@tonic-gate static int		my_volrmmount(char *real_name);
910Sstevel@tonic-gate static int		vol_name_to_dev_node(char *vname, char *found);
920Sstevel@tonic-gate static int		vol_lookup(char *supplied, char *found);
930Sstevel@tonic-gate static device_t		*get_device(char *user_supplied, char *node);
940Sstevel@tonic-gate static char		*get_physical_name(char *path);
950Sstevel@tonic-gate static int		lookup_device(char *supplied, char *found);
960Sstevel@tonic-gate static void		fini_device(device_t *dev);
970Sstevel@tonic-gate static int		is_cd(char *node);
980Sstevel@tonic-gate void			*my_zalloc(size_t size);
990Sstevel@tonic-gate void			err_msg(char *fmt, ...);
1000Sstevel@tonic-gate int			inquiry(int fd, uchar_t *inq);
1010Sstevel@tonic-gate struct uscsi_cmd	*get_uscsi_cmd(void);
1020Sstevel@tonic-gate int			uscsi(int fd, struct uscsi_cmd *scmd);
1030Sstevel@tonic-gate int			get_mode_page(int fd, int page_no, int pc, int buf_len,
1040Sstevel@tonic-gate 			    uchar_t *buffer);
1050Sstevel@tonic-gate int			mode_sense(int fd, uchar_t pc, int dbd, int page_len,
1060Sstevel@tonic-gate 			    uchar_t *buffer);
1070Sstevel@tonic-gate uint16_t		read_scsi16(void *addr);
1080Sstevel@tonic-gate int			check_device(device_t *dev, int cond);
1090Sstevel@tonic-gate static void		get_media_info(device_t *t_dev, char *sdev,
1100Sstevel@tonic-gate 			    char *pname, char *sn);
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate extern void		process_p_flag(smedia_handle_t handle, int32_t fd);
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate void
my_perror(char * err_string)1150Sstevel@tonic-gate my_perror(char *err_string)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	int error_no;
1190Sstevel@tonic-gate 	if (errno == 0)
1200Sstevel@tonic-gate 		return;
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 	error_no = errno;
1230Sstevel@tonic-gate 	(void) fprintf(stderr, "%s", err_string);
1240Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(" : "));
1250Sstevel@tonic-gate 	errno = error_no;
1260Sstevel@tonic-gate 	perror("");
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate int32_t
get_confirmation()1300Sstevel@tonic-gate get_confirmation()
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate 	char c;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("Do you want to continue? (y/n)"));
1350Sstevel@tonic-gate 	c = getchar();
1360Sstevel@tonic-gate 	if (c == 'y' || c == 'Y')
1370Sstevel@tonic-gate 		return (1);
1380Sstevel@tonic-gate 	else if (c == 'n' || c == 'N')
1390Sstevel@tonic-gate 		return (0);
1400Sstevel@tonic-gate 	else {
1410Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Invalid choice\n"));
1420Sstevel@tonic-gate 		return (0);
1430Sstevel@tonic-gate 	}
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate void
get_passwd(struct smwp_state * wp,int32_t confirm)1480Sstevel@tonic-gate get_passwd(struct smwp_state *wp, int32_t confirm)
1490Sstevel@tonic-gate {
1500Sstevel@tonic-gate 	char passwd[256], re_passwd[256];
1510Sstevel@tonic-gate 	int32_t len;
1520Sstevel@tonic-gate 	struct termios tio;
1530Sstevel@tonic-gate 	int32_t echo_off = 0;
1540Sstevel@tonic-gate 	FILE *in, *out;
1550Sstevel@tonic-gate 	char *buf;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	in = fopen("/dev/tty", "r+");
1590Sstevel@tonic-gate 	if (in == NULL) {
1600Sstevel@tonic-gate 		in = stdin;
1610Sstevel@tonic-gate 		out = stderr;
1620Sstevel@tonic-gate 	} else {
1630Sstevel@tonic-gate 		out = in;
1640Sstevel@tonic-gate 	}
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	/* Turn echoing off if it is on now.  */
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	if (tcgetattr(fileno(in), &tio) < 0) {
1690Sstevel@tonic-gate 		PERROR("Echo off ioctl failed");
1700Sstevel@tonic-gate 		exit(1);
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate 	if (tio.c_lflag & ECHO) {
1730Sstevel@tonic-gate 		tio.c_lflag &= ~ECHO;
1740Sstevel@tonic-gate 		/* echo_off = tcsetattr(fileno(in), TCSAFLUSH, &tio) == 0; */
1750Sstevel@tonic-gate 		echo_off = tcsetattr(fileno(in), TCSAFLUSH, &tio) == 0;
1760Sstevel@tonic-gate 		tio.c_lflag |= ECHO;
1770Sstevel@tonic-gate 	}
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	/* CONSTCOND */
1800Sstevel@tonic-gate 	while (1) {
1810Sstevel@tonic-gate 		(void) fputs(
182*9525SPavel.Potoplyak@Sun.COM 		    gettext("Please enter password (32 chars maximum):"),
183*9525SPavel.Potoplyak@Sun.COM 		    out);
1840Sstevel@tonic-gate 		(void) fflush(out);
1850Sstevel@tonic-gate 		buf = fgets(passwd, (size_t)256, in);
1860Sstevel@tonic-gate 		rewind(in);
1870Sstevel@tonic-gate 		if (buf == NULL) {
1880Sstevel@tonic-gate 			PERROR("Error reading password");
1890Sstevel@tonic-gate 			continue;
1900Sstevel@tonic-gate 		}
1910Sstevel@tonic-gate 		len = strlen(passwd);
1920Sstevel@tonic-gate 		(void) fputc('\n', out);
1930Sstevel@tonic-gate 		len--;	/* To offset the \n */
1940Sstevel@tonic-gate 		if ((len <= 0) || (len > 32)) {
1950Sstevel@tonic-gate 			(void) fprintf(stderr,
196*9525SPavel.Potoplyak@Sun.COM 			    gettext("Invalid length of password \n"));
1970Sstevel@tonic-gate 			(void) fputs("Try again\n", out);
1980Sstevel@tonic-gate 			continue;
1990Sstevel@tonic-gate 		}
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 		if (!confirm)
2020Sstevel@tonic-gate 			break;
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 		(void) fputs("Please reenter password:", out);
2050Sstevel@tonic-gate 		(void) fflush(out);
2060Sstevel@tonic-gate 		buf = fgets(re_passwd, (size_t)256, in);
2070Sstevel@tonic-gate 		rewind(in);
2080Sstevel@tonic-gate 		(void) fputc('\n', out);
2090Sstevel@tonic-gate 		if ((buf == NULL) || strcmp(passwd, re_passwd)) {
2100Sstevel@tonic-gate 			(void) fputs("passwords did not match\n", out);
2110Sstevel@tonic-gate 			(void) fputs("Try again\n", out);
2120Sstevel@tonic-gate 		} else {
2130Sstevel@tonic-gate 			break;
2140Sstevel@tonic-gate 		}
2150Sstevel@tonic-gate 	}
2160Sstevel@tonic-gate 	wp->sm_passwd_len = len;
2170Sstevel@tonic-gate 	(void) strncpy(wp->sm_passwd, passwd, wp->sm_passwd_len);
2180Sstevel@tonic-gate 	wp->sm_version = SMWP_STATE_V_1;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	/* Restore echoing.  */
2210Sstevel@tonic-gate 	if (echo_off)
2220Sstevel@tonic-gate 		(void) tcsetattr(fileno(in), TCSAFLUSH, &tio);
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate }
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate int32_t
check_and_unmount_vold(char * device_name,int32_t flag)2270Sstevel@tonic-gate check_and_unmount_vold(char *device_name, int32_t flag)
2280Sstevel@tonic-gate {
2290Sstevel@tonic-gate 	char *real_name;
2300Sstevel@tonic-gate 	char *nm;
2310Sstevel@tonic-gate 	char tmp_path_name[PATH_MAX];
2320Sstevel@tonic-gate 	struct stat stat_buf;
2330Sstevel@tonic-gate 	int32_t ret_val = 0;
2340Sstevel@tonic-gate 	struct	mnttab	*mntp;
2350Sstevel@tonic-gate 	FILE	*fp;
2360Sstevel@tonic-gate 	int nl;
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	DPRINTF1("Device name %s\n", device_name);
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	if (volmgt_running() == 0) {
2410Sstevel@tonic-gate 		DPRINTF("Vold not running\n");
2420Sstevel@tonic-gate 		return (0);
2430Sstevel@tonic-gate 	}
2440Sstevel@tonic-gate 	if ((nm = volmgt_symname(device_name)) == NULL) {
2450Sstevel@tonic-gate 		DPRINTF("path not managed\n");
2460Sstevel@tonic-gate 		real_name = media_findname(device_name);
2470Sstevel@tonic-gate 	} else {
2480Sstevel@tonic-gate 		DPRINTF1("path managed as %s\n", nm);
2490Sstevel@tonic-gate 		real_name = media_findname(nm);
2500Sstevel@tonic-gate 		DPRINTF1("real name %s\n", real_name);
2510Sstevel@tonic-gate 	}
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	if (real_name == NULL)
2540Sstevel@tonic-gate 		return (-1);
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	/*
2570Sstevel@tonic-gate 	 * To find out whether the device has been mounted by
2580Sstevel@tonic-gate 	 * volume manager...
2590Sstevel@tonic-gate 	 *
2600Sstevel@tonic-gate 	 * Convert the real name to a block device address.
2610Sstevel@tonic-gate 	 * Do a partial match with the mnttab entries.
2620Sstevel@tonic-gate 	 * Make sure the match is in the beginning to avoid if
2630Sstevel@tonic-gate 	 * anybody puts a label similiar to volume manager path names.
2640Sstevel@tonic-gate 	 * Then use "volrmmount -e <dev_name>" if -U flag is set.
2650Sstevel@tonic-gate 	 */
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	nl = strlen("/vol/dev/");
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	if (strncmp(real_name, "/vol/dev/", nl) != 0)
2700Sstevel@tonic-gate 			return (0);
2710Sstevel@tonic-gate 	if (real_name[nl] == 'r') {
2720Sstevel@tonic-gate 		(void) snprintf(tmp_path_name, PATH_MAX, "%s%s", "/vol/dev/",
273*9525SPavel.Potoplyak@Sun.COM 		    &real_name[nl + 1]);
2740Sstevel@tonic-gate 	} else {
2750Sstevel@tonic-gate 		(void) snprintf(tmp_path_name, PATH_MAX, "%s", real_name);
2760Sstevel@tonic-gate 	}
2770Sstevel@tonic-gate 	DPRINTF1("%s \n", tmp_path_name);
2780Sstevel@tonic-gate 	ret_val = stat(tmp_path_name, &stat_buf);
2790Sstevel@tonic-gate 	if (ret_val < 0) {
2800Sstevel@tonic-gate 		PERROR("Could not stat");
2810Sstevel@tonic-gate 		return (-1);
2820Sstevel@tonic-gate 	}
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	fp = fopen("/etc/mnttab", "r");
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	if (fp == NULL) {
2870Sstevel@tonic-gate 		PERROR("Could not open /etc/mnttab");
2880Sstevel@tonic-gate 		return (-1);
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	mntp = (struct mnttab *)malloc(sizeof (struct mnttab));
2920Sstevel@tonic-gate 	if (mntp == NULL) {
2930Sstevel@tonic-gate 		PERROR("malloc failed");
2940Sstevel@tonic-gate 		(void) fclose(fp);
2950Sstevel@tonic-gate 		return (-1);
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 	errno = 0;
2980Sstevel@tonic-gate 	while (getmntent(fp, mntp) == 0) {
2990Sstevel@tonic-gate 		if (errno != 0) {
3000Sstevel@tonic-gate 			PERROR("Error with mnttab");
3010Sstevel@tonic-gate 			(void) fclose(fp);
3020Sstevel@tonic-gate 			return (-1);
3030Sstevel@tonic-gate 		}
3040Sstevel@tonic-gate 		/* Is it a probable entry? */
3050Sstevel@tonic-gate 		DPRINTF1(" %s \n", mntp->mnt_special);
3060Sstevel@tonic-gate 		if (strstr(mntp->mnt_special, tmp_path_name) !=
307*9525SPavel.Potoplyak@Sun.COM 		    mntp->mnt_special) {
3080Sstevel@tonic-gate 			/* Skip to next entry */
3090Sstevel@tonic-gate 			continue;
3100Sstevel@tonic-gate 		} else {
3110Sstevel@tonic-gate 			DPRINTF1("Found!! %s\n", mntp->mnt_special);
3120Sstevel@tonic-gate 			ret_val = 1;
3130Sstevel@tonic-gate 			break;
3140Sstevel@tonic-gate 		}
3150Sstevel@tonic-gate 	}
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	if (ret_val == 1) {
3180Sstevel@tonic-gate 		if (flag) {
3190Sstevel@tonic-gate 			if (my_volrmmount(real_name) < 0) {
3200Sstevel@tonic-gate 				ret_val = -1;
3210Sstevel@tonic-gate 			}
3220Sstevel@tonic-gate 		} else {
3230Sstevel@tonic-gate 			ret_val = -1;
3240Sstevel@tonic-gate 		}
3250Sstevel@tonic-gate 	}
3260Sstevel@tonic-gate 	(void) fclose(fp);
3270Sstevel@tonic-gate 	free(mntp);
3280Sstevel@tonic-gate 	return (ret_val);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate /*
3320Sstevel@tonic-gate  * This routine checks if a device has mounted partitions. The
3330Sstevel@tonic-gate  * device name is assumed to be /dev/rdsk/cNtNdNsN. So, this can
3340Sstevel@tonic-gate  * be used for SCSI and PCMCIA cards.
3350Sstevel@tonic-gate  * Returns
3360Sstevel@tonic-gate  *	 0 : if not mounted
3370Sstevel@tonic-gate  *	 1 : if successfully unmounted
3380Sstevel@tonic-gate  *	-1 : Any error or umount failed
3390Sstevel@tonic-gate  */
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate int32_t
check_and_unmount_scsi(char * device_name,int32_t flag)3420Sstevel@tonic-gate check_and_unmount_scsi(char *device_name, int32_t flag)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	struct	mnttab	*mntrefp;
3460Sstevel@tonic-gate 	struct	mnttab	*mntp;
3470Sstevel@tonic-gate 	FILE	*fp;
3480Sstevel@tonic-gate 	char block_dev_name[PATH_MAX];
3490Sstevel@tonic-gate 	char tmp_name[PATH_MAX];
3500Sstevel@tonic-gate 	int32_t  i, j;
3510Sstevel@tonic-gate 	int32_t unmounted = 0;
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	/*
3540Sstevel@tonic-gate 	 * If the device name is not a character special, anyway we
3550Sstevel@tonic-gate 	 * can not progress further
3560Sstevel@tonic-gate 	 */
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	if (strncmp(device_name, "/dev/rdsk/c", strlen("/dev/rdsk/c")) != 0)
3590Sstevel@tonic-gate 		return (0);
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	(void) snprintf(block_dev_name, PATH_MAX, "/dev/%s",
362*9525SPavel.Potoplyak@Sun.COM 	    &device_name[strlen("/dev/r")]);
3630Sstevel@tonic-gate 	fp = fopen("/etc/mnttab", "r");
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	if (fp == NULL) {
3660Sstevel@tonic-gate 		PERROR("Could not open /etc/mnttab");
3670Sstevel@tonic-gate 		return (-1);
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	mntrefp = (struct mnttab *)malloc(sizeof (struct mnttab));
3710Sstevel@tonic-gate 	if (mntrefp == NULL) {
3720Sstevel@tonic-gate 		PERROR("malloc failed");
3730Sstevel@tonic-gate 		(void) fclose(fp);
3740Sstevel@tonic-gate 		return (-1);
3750Sstevel@tonic-gate 	}
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 	mntp = (struct mnttab *)malloc(sizeof (struct mnttab));
3780Sstevel@tonic-gate 	if (mntp == NULL) {
3790Sstevel@tonic-gate 		PERROR("malloc failed");
3800Sstevel@tonic-gate 		(void) fclose(fp);
3810Sstevel@tonic-gate 		free(mntrefp);
3820Sstevel@tonic-gate 		return (-1);
3830Sstevel@tonic-gate 	}
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	/* Try all the partitions */
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	(void) snprintf(tmp_name, PATH_MAX, "/dev/%s",
3880Sstevel@tonic-gate 	    &device_name[strlen("/dev/r")]);
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	tmp_name[strlen("/dev/dsk/c0t0d0s")] = '\0';
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	errno = 0;
3930Sstevel@tonic-gate 	while (getmntent(fp, mntp) == 0) {
3940Sstevel@tonic-gate 		if (errno != 0) {
3950Sstevel@tonic-gate 			PERROR("Error with mnttab");
3960Sstevel@tonic-gate 			(void) fclose(fp);
3970Sstevel@tonic-gate 			return (-1);
3980Sstevel@tonic-gate 		}
3990Sstevel@tonic-gate 		/* Is it a probable entry? */
4000Sstevel@tonic-gate 		if (strncmp(mntp->mnt_special, tmp_name, strlen(tmp_name))) {
4010Sstevel@tonic-gate 			/* Skip to next entry */
4020Sstevel@tonic-gate 			continue;
4030Sstevel@tonic-gate 		}
4040Sstevel@tonic-gate 		for (i = 0; i < NDKMAP; i++) {
4050Sstevel@tonic-gate 			/* Check for ufs style mount devices */
4060Sstevel@tonic-gate 			(void) snprintf(block_dev_name, PATH_MAX,
4070Sstevel@tonic-gate 			    "%s%d", tmp_name, i);
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 			if (strcmp(mntp->mnt_special, block_dev_name) == 0) {
4100Sstevel@tonic-gate 				if (flag) {
4110Sstevel@tonic-gate 					if (my_umount(mntp->mnt_mountp) < 0) {
4120Sstevel@tonic-gate 						(void) fclose(fp);
4130Sstevel@tonic-gate 						return (-1);
4140Sstevel@tonic-gate 					}
4150Sstevel@tonic-gate 					unmounted = 1;
4160Sstevel@tonic-gate 				} else {
4170Sstevel@tonic-gate 					(void) fclose(fp);
4180Sstevel@tonic-gate 					return (-1);
4190Sstevel@tonic-gate 				}
4200Sstevel@tonic-gate 				/* Skip to next entry */
4210Sstevel@tonic-gate 				continue;
4220Sstevel@tonic-gate 			}
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 			/* Try for :1 -> :24 for pcfs */
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 			for (j = 1; j < 24; j++) {
4270Sstevel@tonic-gate 				(void) snprintf(block_dev_name, PATH_MAX,
4280Sstevel@tonic-gate 				    "%s%d:%d", tmp_name, i, j);
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 				if (strcmp(mntp->mnt_special,
431*9525SPavel.Potoplyak@Sun.COM 				    block_dev_name) == 0) {
4320Sstevel@tonic-gate 					if (flag) {
4330Sstevel@tonic-gate 						if (my_umount(mntp->mnt_mountp)
434*9525SPavel.Potoplyak@Sun.COM 						    < 0) {
4350Sstevel@tonic-gate 							(void) fclose(fp);
4360Sstevel@tonic-gate 							return (-1);
4370Sstevel@tonic-gate 						}
4380Sstevel@tonic-gate 						unmounted = 1;
4390Sstevel@tonic-gate 					} else {
4400Sstevel@tonic-gate 						(void) fclose(fp);
4410Sstevel@tonic-gate 						return (-1);
4420Sstevel@tonic-gate 					}
4430Sstevel@tonic-gate 					/* Skip to next entry */
4440Sstevel@tonic-gate 					continue;
4450Sstevel@tonic-gate 				}
4460Sstevel@tonic-gate 				(void) snprintf(block_dev_name, PATH_MAX,
4470Sstevel@tonic-gate 				    "%s%d:%c", tmp_name, i, 'b' + j);
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 				if (strcmp(mntp->mnt_special,
450*9525SPavel.Potoplyak@Sun.COM 				    block_dev_name) == 0) {
4510Sstevel@tonic-gate 					if (flag) {
4520Sstevel@tonic-gate 						if (my_umount(mntp->mnt_mountp)
453*9525SPavel.Potoplyak@Sun.COM 						    < 0) {
4540Sstevel@tonic-gate 							(void) fclose(fp);
4550Sstevel@tonic-gate 							return (-1);
4560Sstevel@tonic-gate 						}
4570Sstevel@tonic-gate 						unmounted = 1;
4580Sstevel@tonic-gate 					} else {
4590Sstevel@tonic-gate 						(void) fclose(fp);
4600Sstevel@tonic-gate 						return (-1);
4610Sstevel@tonic-gate 					}
4620Sstevel@tonic-gate 					/* Skip to next entry */
4630Sstevel@tonic-gate 					continue;
4640Sstevel@tonic-gate 				}
4650Sstevel@tonic-gate 			}
4660Sstevel@tonic-gate 		}
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 	}
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	if (unmounted)
4710Sstevel@tonic-gate 		return (1);
4720Sstevel@tonic-gate 	return (0);
4730Sstevel@tonic-gate }
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate /*
4760Sstevel@tonic-gate  * This routine checks if a device has mounted partitions. The
4770Sstevel@tonic-gate  * device name is assumed to be /dev/rdiskette. So, this can
4780Sstevel@tonic-gate  * be used for Floppy controllers
4790Sstevel@tonic-gate  * Returns
4800Sstevel@tonic-gate  *	 0 : if not mounted
4810Sstevel@tonic-gate  *	 1 : if successfully unmounted
4820Sstevel@tonic-gate  *	-1 : Any error or unmount failed
4830Sstevel@tonic-gate  */
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate int32_t
check_and_unmount_floppy(int32_t fd,int32_t flag)4860Sstevel@tonic-gate check_and_unmount_floppy(int32_t fd, int32_t flag)
4870Sstevel@tonic-gate {
4880Sstevel@tonic-gate 	FILE	*fp = NULL;
4890Sstevel@tonic-gate 	int32_t	mfd;
4900Sstevel@tonic-gate 	struct dk_cinfo dkinfo, dkinfo_tmp;
4910Sstevel@tonic-gate 	struct mnttab	mnt_record;
4920Sstevel@tonic-gate 	struct mnttab	*mp = &mnt_record;
4930Sstevel@tonic-gate 	struct stat	stbuf;
4940Sstevel@tonic-gate 	char	raw_device[PATH_MAX];
4950Sstevel@tonic-gate 	int32_t	found = 0;
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &dkinfo) < 0) {
4990Sstevel@tonic-gate 		return (-1);
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	if ((fp = fopen(MNTTAB, "r")) == NULL) {
5030Sstevel@tonic-gate 		PERROR("Could not open /etc/mnttab");
5040Sstevel@tonic-gate 		(void) close(fd);
5050Sstevel@tonic-gate 		exit(3);
5060Sstevel@tonic-gate 	}
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	while (getmntent(fp, mp) == 0) {
5090Sstevel@tonic-gate 		if (strstr(mp->mnt_special, "/dev/fd") == NULL &&
5100Sstevel@tonic-gate 		    strstr(mp->mnt_special, "/dev/disket") == NULL &&
5110Sstevel@tonic-gate 		    strstr(mp->mnt_special, "/dev/c") == NULL) {
5120Sstevel@tonic-gate 			continue;
5130Sstevel@tonic-gate 		}
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 		(void) strcpy(raw_device, "/dev/r");
5160Sstevel@tonic-gate 		(void) strcat(raw_device, mp->mnt_special + strlen("/dev/"));
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 		/*
5200Sstevel@tonic-gate 		 * Attempt to open the device.	If it fails, skip it.
5210Sstevel@tonic-gate 		 */
5220Sstevel@tonic-gate 
5232160Szk194757 		/* Turn on the privileges. */
5242160Szk194757 		(void) __priv_bracket(PRIV_ON);
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 		mfd = open(raw_device, O_RDWR | O_NDELAY);
5270Sstevel@tonic-gate 
5282160Szk194757 		/* Turn off the privileges. */
5292160Szk194757 		(void) __priv_bracket(PRIV_OFF);
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 		if (mfd < 0) {
5320Sstevel@tonic-gate 			continue;
5330Sstevel@tonic-gate 		}
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 		/*
5360Sstevel@tonic-gate 		 * Must be a character device
5370Sstevel@tonic-gate 		 */
5380Sstevel@tonic-gate 		if (fstat(mfd, &stbuf) < 0 || !S_ISCHR(stbuf.st_mode)) {
5390Sstevel@tonic-gate 			(void) close(mfd);
5400Sstevel@tonic-gate 			continue;
5410Sstevel@tonic-gate 		}
5420Sstevel@tonic-gate 		/*
5430Sstevel@tonic-gate 		 * Attempt to read the configuration info on the disk.
5440Sstevel@tonic-gate 		 */
5450Sstevel@tonic-gate 		if (ioctl(mfd, DKIOCINFO, &dkinfo_tmp) < 0) {
5460Sstevel@tonic-gate 			(void) close(mfd);
5470Sstevel@tonic-gate 			continue;
5480Sstevel@tonic-gate 		}
5490Sstevel@tonic-gate 		/*
5500Sstevel@tonic-gate 		 * Finished with the opened device
5510Sstevel@tonic-gate 		 */
5520Sstevel@tonic-gate 		(void) close(mfd);
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 		/*
5550Sstevel@tonic-gate 		 * If it's not the disk we're interested in, it doesn't apply.
5560Sstevel@tonic-gate 		 */
5570Sstevel@tonic-gate 		if (dkinfo.dki_ctype != dkinfo_tmp.dki_ctype ||
558*9525SPavel.Potoplyak@Sun.COM 		    dkinfo.dki_cnum != dkinfo_tmp.dki_cnum ||
559*9525SPavel.Potoplyak@Sun.COM 		    dkinfo.dki_unit != dkinfo_tmp.dki_unit) {
5600Sstevel@tonic-gate 				continue;
5610Sstevel@tonic-gate 		}
5620Sstevel@tonic-gate 		/*
5630Sstevel@tonic-gate 		 * It's a mount on the disk we're checking.  If we are
5640Sstevel@tonic-gate 		 * checking whole disk, then we found trouble.	We can
5650Sstevel@tonic-gate 		 * quit searching.
5660Sstevel@tonic-gate 		 */
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 		if (flag) {
5690Sstevel@tonic-gate 			if (my_umount(mp->mnt_mountp) < 0) {
5700Sstevel@tonic-gate 				return (-1);
5710Sstevel@tonic-gate 			}
5720Sstevel@tonic-gate 			found = 1;
5730Sstevel@tonic-gate 		} else {
5740Sstevel@tonic-gate 			return (-1);
5750Sstevel@tonic-gate 		}
5760Sstevel@tonic-gate 	}
5770Sstevel@tonic-gate 	return (found);
5780Sstevel@tonic-gate }
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate int32_t
my_open(char * device_name,int32_t flags)5820Sstevel@tonic-gate my_open(char *device_name, int32_t flags)
5830Sstevel@tonic-gate {
5840Sstevel@tonic-gate 	char *real_name;
5850Sstevel@tonic-gate 	char *nm;
5860Sstevel@tonic-gate 	char tmp_path_name[PATH_MAX];
5870Sstevel@tonic-gate 	struct stat stat_buf;
5880Sstevel@tonic-gate 	int32_t ret_val;
5890Sstevel@tonic-gate 	int32_t fd;
5900Sstevel@tonic-gate 	int32_t have_read_priv = 0;
5910Sstevel@tonic-gate 	DIR *dirp;
5920Sstevel@tonic-gate 	struct dirent *dp;
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	DPRINTF1("Device name %s\n", device_name);
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	if ((nm = volmgt_symname(device_name)) == NULL) {
5970Sstevel@tonic-gate 		DPRINTF("path not managed\n");
5980Sstevel@tonic-gate 		real_name = media_findname(device_name);
5990Sstevel@tonic-gate 	} else {
6000Sstevel@tonic-gate 		DPRINTF1("path managed as %s\n", nm);
6010Sstevel@tonic-gate 		real_name = media_findname(nm);
6020Sstevel@tonic-gate 		DPRINTF1("real name %s\n", real_name);
6030Sstevel@tonic-gate 	}
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	if (real_name == NULL)
6060Sstevel@tonic-gate 		return (-1);
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate 	(void) strcpy(tmp_path_name, real_name);
6090Sstevel@tonic-gate 	ret_val = stat(tmp_path_name, &stat_buf);
6100Sstevel@tonic-gate 	if (ret_val < 0) {
6110Sstevel@tonic-gate 		PERROR("Could not stat");
6120Sstevel@tonic-gate 		return (-1);
6130Sstevel@tonic-gate 	}
614871Scasper 	if (S_ISDIR(stat_buf.st_mode)) {
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 		/*
6170Sstevel@tonic-gate 		 * Open the directory and look for the
6180Sstevel@tonic-gate 		 * first non '.' entry.
6190Sstevel@tonic-gate 		 * Since raw_read and raw_writes are used, we don't
6200Sstevel@tonic-gate 		 * need to access the backup slice.
6210Sstevel@tonic-gate 		 * For PCMCIA Memory cards, raw_read and raw_writes are
6220Sstevel@tonic-gate 		 * not supported, but that is not a problem as, only slice2
6230Sstevel@tonic-gate 		 * is allowed on PCMCIA memory cards.
6240Sstevel@tonic-gate 		 */
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 		/*
6270Sstevel@tonic-gate 		 * First make sure we are operating with a /vol/....
6280Sstevel@tonic-gate 		 * Otherwise it can dangerous,
6290Sstevel@tonic-gate 		 * e.g. rmformat -s /dev/rdsk
6300Sstevel@tonic-gate 		 * We should not look into the directory contents here.
6310Sstevel@tonic-gate 		 */
6320Sstevel@tonic-gate 		if (strncmp(tmp_path_name, "/vol/dev/", strlen("/vol/dev/"))
633*9525SPavel.Potoplyak@Sun.COM 		    != 0) {
6340Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("The specified device \
6350Sstevel@tonic-gate is not a raw device.\n"));
6360Sstevel@tonic-gate 			exit(1);
6370Sstevel@tonic-gate 		}
6380Sstevel@tonic-gate 
6392160Szk194757 		/* Turn on the privileges. */
6402160Szk194757 		(void) __priv_bracket(PRIV_ON);
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 		dirp = opendir(tmp_path_name);
6430Sstevel@tonic-gate 
6442160Szk194757 		/* Turn off the privileges. */
6452160Szk194757 		(void) __priv_bracket(PRIV_OFF);
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 		if (dirp == NULL) {
6480Sstevel@tonic-gate 			return (-1);
6490Sstevel@tonic-gate 		}
6500Sstevel@tonic-gate 
6512160Szk194757 		/* Turn on the privileges. */
6522160Szk194757 		(void) __priv_bracket(PRIV_ON);
6530Sstevel@tonic-gate 		have_read_priv = 1;
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 		while ((dp = readdir(dirp)) != NULL) {
6560Sstevel@tonic-gate 
6572160Szk194757 			/* Turn off the privileges. */
6582160Szk194757 			(void) __priv_bracket(PRIV_OFF);
6590Sstevel@tonic-gate 			have_read_priv = 0;
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 			DPRINTF1("Found %s\n", dp->d_name);
6620Sstevel@tonic-gate 			if ((strcmp(dp->d_name, ".") != 0) &&
6630Sstevel@tonic-gate 			    (strcmp(dp->d_name, "..") != 0)) {
6640Sstevel@tonic-gate 				(void) snprintf(tmp_path_name, PATH_MAX,
6650Sstevel@tonic-gate 				    "%s/%s", tmp_path_name, dp->d_name);
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 				DPRINTF1("tmp_pathname is %s\n", tmp_path_name);
6680Sstevel@tonic-gate 				break;
6690Sstevel@tonic-gate 			}
6700Sstevel@tonic-gate 
6712160Szk194757 			/* Turn on the privileges. */
6722160Szk194757 			(void) __priv_bracket(PRIV_ON);
6730Sstevel@tonic-gate 			have_read_priv = 1;
6740Sstevel@tonic-gate 		}
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 		if (have_read_priv) {
6770Sstevel@tonic-gate 			/* drop the file_dac_read privilege */
6782160Szk194757 			(void) __priv_bracket(PRIV_OFF);
6790Sstevel@tonic-gate 			have_read_priv = 0;
6800Sstevel@tonic-gate 		}
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 		(void) closedir(dirp);
6830Sstevel@tonic-gate 	}
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 	if (volmgt_running() == 0) {
6872160Szk194757 		/* Turn on privileges. */
6882160Szk194757 		(void) __priv_bracket(PRIV_ON);
6890Sstevel@tonic-gate 		have_read_priv = 1;
6900Sstevel@tonic-gate 	}
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 	fd = open(tmp_path_name, flags);
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	if (have_read_priv) {
6952160Szk194757 		/* Turn off privileges. */
6962160Szk194757 		(void) __priv_bracket(PRIV_OFF);
6970Sstevel@tonic-gate 		have_read_priv = 0;
6980Sstevel@tonic-gate 	}
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate 	DPRINTF1("path opened %s\n", tmp_path_name);
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 	return (fd);
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate 
7057563SPrasad.Singamsetty@Sun.COM uint64_t
my_atoll(char * ptr)7060Sstevel@tonic-gate my_atoll(char *ptr)
7070Sstevel@tonic-gate {
7080Sstevel@tonic-gate 	char *tmp_ptr = ptr;
7090Sstevel@tonic-gate 	int32_t base = 10;
7107563SPrasad.Singamsetty@Sun.COM 	uint64_t ret_val;
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate 	while (*tmp_ptr) {
7130Sstevel@tonic-gate 		if (isdigit(*tmp_ptr))
7140Sstevel@tonic-gate 			tmp_ptr++;
7150Sstevel@tonic-gate 		else {
7160Sstevel@tonic-gate 			base = 16;
7170Sstevel@tonic-gate 			break;
7180Sstevel@tonic-gate 		}
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 	tmp_ptr = ptr;
7210Sstevel@tonic-gate 	if (base == 16) {
7220Sstevel@tonic-gate 		if (strlen(tmp_ptr) < 3) {
7230Sstevel@tonic-gate 			return (-1);
7240Sstevel@tonic-gate 		}
7250Sstevel@tonic-gate 		if (*tmp_ptr++ != '0' || (*tmp_ptr != 'x' && *tmp_ptr != 'X')) {
7260Sstevel@tonic-gate 			return (-1);
7270Sstevel@tonic-gate 		}
7280Sstevel@tonic-gate 		tmp_ptr++;
7290Sstevel@tonic-gate 		while (*tmp_ptr) {
7300Sstevel@tonic-gate 			if (isxdigit(*tmp_ptr))
7310Sstevel@tonic-gate 				tmp_ptr++;
7320Sstevel@tonic-gate 			else {
7330Sstevel@tonic-gate 				return (-1);
7340Sstevel@tonic-gate 			}
7350Sstevel@tonic-gate 		}
7360Sstevel@tonic-gate 	}
7377563SPrasad.Singamsetty@Sun.COM 	ret_val = (uint64_t)strtoull(ptr, (char **)NULL, 0);
7380Sstevel@tonic-gate 	return (ret_val);
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate int32_t
write_sunos_label(int32_t fd,int32_t media_type)7420Sstevel@tonic-gate write_sunos_label(int32_t fd, int32_t media_type)
7430Sstevel@tonic-gate {
7440Sstevel@tonic-gate 
7457563SPrasad.Singamsetty@Sun.COM 	struct extvtoc v_toc;
7460Sstevel@tonic-gate 	int32_t ret;
7470Sstevel@tonic-gate 
7487563SPrasad.Singamsetty@Sun.COM 	(void) memset(&v_toc, 0, sizeof (struct extvtoc));
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate 	/* Initialize the vtoc information */
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 	if (media_type == SM_FLOPPY) {
7530Sstevel@tonic-gate 		struct fd_char fdchar;
7540Sstevel@tonic-gate 		int32_t mult_factor;
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 		if (ioctl(fd, FDIOGCHAR, &fdchar) < 0) {
7570Sstevel@tonic-gate 			PERROR("FDIOGCHAR failed");
7580Sstevel@tonic-gate 			return (-1);
7590Sstevel@tonic-gate 		}
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate 		/* SPARC and x86 fd drivers use fdc_medium differently */
7620Sstevel@tonic-gate #if defined(__sparc)
7630Sstevel@tonic-gate 		mult_factor = (fdchar.fdc_medium) ? 2 : 1;
7640Sstevel@tonic-gate #elif defined(__x86)
7650Sstevel@tonic-gate 		mult_factor = (fdchar.fdc_medium == 5) ? 2 : 1;
7660Sstevel@tonic-gate #else
7670Sstevel@tonic-gate #error  No Platform defined
7680Sstevel@tonic-gate #endif /* defined(__sparc) */
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 		/* initialize the vtoc structure */
7710Sstevel@tonic-gate 		v_toc.v_nparts = 3;
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 		v_toc.v_part[0].p_start = 0;
7740Sstevel@tonic-gate 		v_toc.v_part[0].p_size = (fdchar.fdc_ncyl - 1) * 2 *
775*9525SPavel.Potoplyak@Sun.COM 		    fdchar.fdc_secptrack * mult_factor;
7760Sstevel@tonic-gate 		v_toc.v_part[1].p_start = (fdchar.fdc_ncyl - 1) * 2 *
777*9525SPavel.Potoplyak@Sun.COM 		    fdchar.fdc_secptrack * mult_factor;
7780Sstevel@tonic-gate 		v_toc.v_part[1].p_size = 2 * fdchar.fdc_secptrack * mult_factor;
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 		v_toc.v_part[2].p_start = 0;
7810Sstevel@tonic-gate 		v_toc.v_part[2].p_size = fdchar.fdc_ncyl * 2 *
782*9525SPavel.Potoplyak@Sun.COM 		    fdchar.fdc_secptrack * mult_factor;
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 	} else if (media_type == SM_SCSI_FLOPPY) {
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate 		smedia_handle_t handle;
7870Sstevel@tonic-gate 		smmedium_prop_t med_info;
7880Sstevel@tonic-gate 		struct dk_geom dkgeom;
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 		/*
7920Sstevel@tonic-gate 		 * call smedia_get_medium_property to get the
7930Sstevel@tonic-gate 		 * correct media information, since DKIOCGMEDIAINFO
7940Sstevel@tonic-gate 		 * may fail for unformatted media.
7950Sstevel@tonic-gate 		 */
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 		handle = smedia_get_handle(fd);
7980Sstevel@tonic-gate 		if (handle == NULL) {
7990Sstevel@tonic-gate 			(void) fprintf(stderr,
8000Sstevel@tonic-gate 			gettext("Failed to get libsmedia handle.\n"));
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 			(void) close(fd);
8030Sstevel@tonic-gate 			return (-1);
8040Sstevel@tonic-gate 		}
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 		if (smedia_get_medium_property(handle, &med_info) < 0) {
8080Sstevel@tonic-gate 			(void) fprintf(stderr,
8090Sstevel@tonic-gate 			    gettext("Get medium property failed \n"));
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 			(void) smedia_release_handle(handle);
8120Sstevel@tonic-gate 			(void) close(fd);
8130Sstevel@tonic-gate 			return (-1);
8140Sstevel@tonic-gate 		}
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 		/* Fill in our own geometry information */
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 		dkgeom.dkg_pcyl = med_info.sm_pcyl;
8190Sstevel@tonic-gate 		dkgeom.dkg_ncyl = med_info.sm_pcyl;
8200Sstevel@tonic-gate 		dkgeom.dkg_nhead = med_info.sm_nhead;
8210Sstevel@tonic-gate 		dkgeom.dkg_nsect = med_info.sm_nsect;
8220Sstevel@tonic-gate 		dkgeom.dkg_acyl = 0;
8230Sstevel@tonic-gate 		dkgeom.dkg_bcyl = 0;
8240Sstevel@tonic-gate 		dkgeom.dkg_intrlv = 0;
8250Sstevel@tonic-gate 		dkgeom.dkg_apc = 0;
8260Sstevel@tonic-gate 
8270Sstevel@tonic-gate 		/*
8280Sstevel@tonic-gate 		 * Try to set vtoc, if not successful we will
8290Sstevel@tonic-gate 		 * continue to use the faked geometry information.
8300Sstevel@tonic-gate 		 */
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate 		(void) ioctl(fd, DKIOCSGEOM, &dkgeom);
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 		(void) smedia_release_handle(handle);
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 		/* we want the same partitioning as used for normal floppies */
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate 		v_toc.v_part[0].p_start = 0;
8397563SPrasad.Singamsetty@Sun.COM 		v_toc.v_part[0].p_size =  (diskaddr_t)(dkgeom.dkg_ncyl - 1) *
8400Sstevel@tonic-gate 		    dkgeom.dkg_nhead * dkgeom.dkg_nsect;
8410Sstevel@tonic-gate 
8427563SPrasad.Singamsetty@Sun.COM 		v_toc.v_part[1].p_start = (diskaddr_t)(dkgeom.dkg_ncyl - 1) *
8430Sstevel@tonic-gate 		    dkgeom.dkg_nhead * dkgeom.dkg_nsect;
8440Sstevel@tonic-gate 		v_toc.v_part[1].p_size =  dkgeom.dkg_nhead * dkgeom.dkg_nsect;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 		v_toc.v_part[2].p_start = 0;
8477563SPrasad.Singamsetty@Sun.COM 		v_toc.v_part[2].p_size = (diskaddr_t)dkgeom.dkg_ncyl *
8480Sstevel@tonic-gate 		    dkgeom.dkg_nhead * dkgeom.dkg_nsect;
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 		/* both write_vtoc and DKIOCSVTOC require V_NUMPAR partitions */
8510Sstevel@tonic-gate 		v_toc.v_nparts = V_NUMPAR;
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 	} else {
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate 		return (0);
8560Sstevel@tonic-gate 	}
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate 	v_toc.v_sanity = VTOC_SANE;
8590Sstevel@tonic-gate 	v_toc.v_version = V_VERSION;
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate 	/*
8620Sstevel@tonic-gate 	 * The label structure is set up for DEV_BSIZE(512 byte) blocks,
8630Sstevel@tonic-gate 	 * even though a medium density diskette has 1024 byte blocks
8640Sstevel@tonic-gate 	 * See dklabel.h for more details.
8650Sstevel@tonic-gate 	 */
8660Sstevel@tonic-gate 	v_toc.v_sectorsz = DEV_BSIZE;
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 	/* let the fd driver finish constructing the label and writing it. */
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 
8712160Szk194757 	/* Turn on the privileges. */
8722160Szk194757 	(void) __priv_bracket(PRIV_ON);
8730Sstevel@tonic-gate 
8747563SPrasad.Singamsetty@Sun.COM 	ret = write_extvtoc(fd, &v_toc);
8750Sstevel@tonic-gate 
8762160Szk194757 	/* Turn off the privileges. */
8772160Szk194757 	(void) __priv_bracket(PRIV_OFF);
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 	if (ret < 0) {
8800Sstevel@tonic-gate 		PERROR("Write vtoc");
8810Sstevel@tonic-gate 		DPRINTF1("Write vtoc failed errno:%d\n", errno);
8820Sstevel@tonic-gate 		return (-1);
8830Sstevel@tonic-gate 	}
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate 	return (0);
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate static void
intr_sig_handler()8890Sstevel@tonic-gate intr_sig_handler()
8900Sstevel@tonic-gate {
8910Sstevel@tonic-gate 	char c;
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(global_intr_msg));
8940Sstevel@tonic-gate 	(void) fprintf(stderr,
8950Sstevel@tonic-gate 	    gettext("\nDo you want to stop formatting?(y/n)"));
8960Sstevel@tonic-gate 	(void) fflush(stdout);
8970Sstevel@tonic-gate 	rewind(stdin);
898*9525SPavel.Potoplyak@Sun.COM 	while ((c = getchar()) == -1)
899*9525SPavel.Potoplyak@Sun.COM 		;
9000Sstevel@tonic-gate 	if (c == 'y' || c == 'Y') {
9010Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Format interrupted\n"));
9020Sstevel@tonic-gate 		exit(1);
9030Sstevel@tonic-gate 	} else if (c == 'n' || c == 'N')
9040Sstevel@tonic-gate 		return;
9050Sstevel@tonic-gate 	else {
9060Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Did not interrupt\n"));
9070Sstevel@tonic-gate 		return;
9080Sstevel@tonic-gate 	}
9090Sstevel@tonic-gate }
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate static struct sigaction act, oact;
9120Sstevel@tonic-gate void
trap_SIGINT()9130Sstevel@tonic-gate trap_SIGINT()
9140Sstevel@tonic-gate {
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 	act.sa_handler = intr_sig_handler;
9170Sstevel@tonic-gate 	(void) memset(&act.sa_mask, 0, sizeof (sigset_t));
9180Sstevel@tonic-gate 	act.sa_flags = SA_RESTART; /* | SA_NODEFER; */
9190Sstevel@tonic-gate 	if (sigaction(SIGINT, &act, &oact) < 0) {
9200Sstevel@tonic-gate 		DPRINTF("sigset failed\n");
9210Sstevel@tonic-gate 		return;
9220Sstevel@tonic-gate 	}
9230Sstevel@tonic-gate }
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate void
release_SIGINT()9260Sstevel@tonic-gate release_SIGINT()
9270Sstevel@tonic-gate {
9280Sstevel@tonic-gate 	if (sigaction(SIGINT, &oact, (struct sigaction *)NULL) < 0) {
9290Sstevel@tonic-gate 		DPRINTF("sigunset failed\n");
9300Sstevel@tonic-gate 		return;
9310Sstevel@tonic-gate 	}
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate 
9340Sstevel@tonic-gate int32_t
verify(smedia_handle_t handle,int32_t fd,diskaddr_t start_sector,uint32_t nblocks,char * buf,int32_t flag,int32_t blocksize,int32_t no_raw_rw)9357563SPrasad.Singamsetty@Sun.COM verify(smedia_handle_t handle, int32_t fd, diskaddr_t start_sector,
9360Sstevel@tonic-gate 	uint32_t nblocks, char *buf,
9377563SPrasad.Singamsetty@Sun.COM 	int32_t flag, int32_t blocksize, int32_t no_raw_rw)
9380Sstevel@tonic-gate {
9397563SPrasad.Singamsetty@Sun.COM 	uint64_t ret;
9400Sstevel@tonic-gate 
9410Sstevel@tonic-gate 	DPRINTF("ANALYSE MEDIA \n");
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate 	if ((flag == VERIFY_READ) && (!no_raw_rw)) {
9450Sstevel@tonic-gate 
9462160Szk194757 		/* Turn on the privileges. */
9472160Szk194757 		(void) __priv_bracket(PRIV_ON);
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 		ret = smedia_raw_read(handle, start_sector, buf, nblocks *
950*9525SPavel.Potoplyak@Sun.COM 		    blocksize);
9510Sstevel@tonic-gate 
9522160Szk194757 		/* Turn off the privileges. */
9532160Szk194757 		(void) __priv_bracket(PRIV_OFF);
9540Sstevel@tonic-gate 
9557563SPrasad.Singamsetty@Sun.COM 		if (ret != (nblocks * blocksize))
9567563SPrasad.Singamsetty@Sun.COM 			return (-1);
9570Sstevel@tonic-gate 		return (0);
9580Sstevel@tonic-gate 
9597563SPrasad.Singamsetty@Sun.COM 	} else if ((flag == VERIFY_WRITE) && (!no_raw_rw)) {
9600Sstevel@tonic-gate 
9612160Szk194757 		/* Turn on privileges. */
9622160Szk194757 		(void) __priv_bracket(PRIV_ON);
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 		ret = smedia_raw_write(handle, start_sector, buf, nblocks *
965*9525SPavel.Potoplyak@Sun.COM 		    blocksize);
9660Sstevel@tonic-gate 
9672160Szk194757 		/* Turn off the privileges. */
9682160Szk194757 		(void) __priv_bracket(PRIV_OFF);
9690Sstevel@tonic-gate 
9707563SPrasad.Singamsetty@Sun.COM 		if (ret != (blocksize * nblocks))
9710Sstevel@tonic-gate 			return (-1);
9720Sstevel@tonic-gate 		return (0);
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 	} else if ((flag == VERIFY_READ) && (no_raw_rw)) {
9750Sstevel@tonic-gate 		ret = llseek(fd, start_sector * blocksize, SEEK_SET);
9760Sstevel@tonic-gate 		if (ret != start_sector * blocksize) {
9770Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Seek failed\n"));
9780Sstevel@tonic-gate 			return (-2);
9790Sstevel@tonic-gate 		}
9800Sstevel@tonic-gate 
9812160Szk194757 		/* Turn on the privileges. */
9822160Szk194757 		(void) __priv_bracket(PRIV_ON);
9830Sstevel@tonic-gate 
9840Sstevel@tonic-gate 		ret = read(fd, buf, nblocks * blocksize);
9850Sstevel@tonic-gate 
9862160Szk194757 		/* Turn off the privileges. */
9872160Szk194757 		(void) __priv_bracket(PRIV_OFF);
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 		if (ret != nblocks * blocksize) {
9900Sstevel@tonic-gate 			return (-1);
9910Sstevel@tonic-gate 		}
9920Sstevel@tonic-gate 		return (0);
9930Sstevel@tonic-gate 	} else if ((flag == VERIFY_WRITE) && (no_raw_rw)) {
9940Sstevel@tonic-gate 		ret = llseek(fd, start_sector * blocksize, SEEK_SET);
9950Sstevel@tonic-gate 		if (ret != start_sector * blocksize) {
9960Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Seek failed\n"));
9970Sstevel@tonic-gate 			return (-2);
9980Sstevel@tonic-gate 		}
9990Sstevel@tonic-gate 
10002160Szk194757 		/* Turn on the privileges. */
10012160Szk194757 		(void) __priv_bracket(PRIV_ON);
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate 		ret = write(fd, buf, nblocks * blocksize);
10040Sstevel@tonic-gate 
10052160Szk194757 		/* Turn off the privileges. */
10062160Szk194757 		(void) __priv_bracket(PRIV_OFF);
10070Sstevel@tonic-gate 
10080Sstevel@tonic-gate 		if (ret != nblocks * blocksize) {
10090Sstevel@tonic-gate 			return (-1);
10100Sstevel@tonic-gate 		}
10110Sstevel@tonic-gate 		return (0);
10120Sstevel@tonic-gate 	} else {
10130Sstevel@tonic-gate 		DPRINTF("Illegal parameter to verify_analysis!\n");
10140Sstevel@tonic-gate 		return (-1);
10150Sstevel@tonic-gate 	}
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate static int
my_umount(char * mountp)10190Sstevel@tonic-gate my_umount(char *mountp)
10200Sstevel@tonic-gate {
10210Sstevel@tonic-gate 	pid_t	pid;	/* forked proc's pid */
10220Sstevel@tonic-gate 	int	rval;	/* proc's return value */
10230Sstevel@tonic-gate 
10240Sstevel@tonic-gate 
10250Sstevel@tonic-gate 	/* create a child to unmount the path */
10260Sstevel@tonic-gate 
10272160Szk194757 	/* Turn on the privileges */
10282160Szk194757 	(void) __priv_bracket(PRIV_ON);
10290Sstevel@tonic-gate 
10300Sstevel@tonic-gate 	pid = fork();
10310Sstevel@tonic-gate 
10322160Szk194757 	/* Turn off the privileges. */
10332160Szk194757 	(void) __priv_bracket(PRIV_OFF);
10340Sstevel@tonic-gate 
10350Sstevel@tonic-gate 	if (pid < 0) {
10360Sstevel@tonic-gate 		PERROR("fork failed");
10370Sstevel@tonic-gate 		exit(0);
10380Sstevel@tonic-gate 	}
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 	if (pid == 0) {
10410Sstevel@tonic-gate 		/* the child */
10420Sstevel@tonic-gate 		/* get rid of those nasty err messages */
10430Sstevel@tonic-gate 		DPRINTF1("call_unmount_prog: calling %s \n", mountp);
10440Sstevel@tonic-gate 
10452160Szk194757 		/* Turn on the priviliges. */
10462160Szk194757 		(void) __priv_bracket(PRIV_ON);
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 		if (execl("/usr/sbin/umount", "/usr/sbin/umount", mountp,
1049*9525SPavel.Potoplyak@Sun.COM 		    NULL) < 0) {
10500Sstevel@tonic-gate 			perror("exec failed");
10512160Szk194757 			/* Turn off the privileges */
10522160Szk194757 			(void) __priv_bracket(PRIV_OFF);
10530Sstevel@tonic-gate 			exit(-1);
10540Sstevel@tonic-gate 		}
10550Sstevel@tonic-gate 	}
10560Sstevel@tonic-gate 
10570Sstevel@tonic-gate 	/* wait for the umount command to exit */
10580Sstevel@tonic-gate 	rval = 0;
10590Sstevel@tonic-gate 	if (waitpid(pid, &rval, 0) == pid) {
10600Sstevel@tonic-gate 		if (WIFEXITED(rval)) {
10610Sstevel@tonic-gate 			if (WEXITSTATUS(rval) == 0) {
10620Sstevel@tonic-gate 				DPRINTF("umount : Success\n");
10630Sstevel@tonic-gate 				return (1);
10640Sstevel@tonic-gate 			}
10650Sstevel@tonic-gate 		}
10660Sstevel@tonic-gate 	}
10670Sstevel@tonic-gate 	return (-1);
10680Sstevel@tonic-gate }
10690Sstevel@tonic-gate 
10700Sstevel@tonic-gate static int
my_volrmmount(char * real_name)10710Sstevel@tonic-gate my_volrmmount(char *real_name)
10720Sstevel@tonic-gate {
10730Sstevel@tonic-gate 	int pid, rval;
10740Sstevel@tonic-gate 
10752160Szk194757 	/* Turn on the privileges. */
10762160Szk194757 	(void) __priv_bracket(PRIV_ON);
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate 	pid = fork();
10790Sstevel@tonic-gate 
10802160Szk194757 	/* Turn off the privileges. */
10812160Szk194757 	(void) __priv_bracket(PRIV_OFF);
10820Sstevel@tonic-gate 
10830Sstevel@tonic-gate 	/* create a child to unmount the path */
10840Sstevel@tonic-gate 	if (pid < 0) {
10850Sstevel@tonic-gate 		PERROR("fork failed");
10860Sstevel@tonic-gate 		exit(0);
10870Sstevel@tonic-gate 	}
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate 	if (pid == 0) {
10900Sstevel@tonic-gate 		/* the child */
10910Sstevel@tonic-gate 		/* get rid of those nasty err messages */
10920Sstevel@tonic-gate 		DPRINTF1("call_unmount_prog: calling %s \n",
1093*9525SPavel.Potoplyak@Sun.COM 		    "/usr/bin/volrmmount");
10940Sstevel@tonic-gate 
10952160Szk194757 		/* Turn on the privileges. */
10962160Szk194757 		(void) __priv_bracket(PRIV_ON);
10970Sstevel@tonic-gate 		if (execl("/usr/bin/volrmmount", "/usr/bin/volrmmount", "-e",
1098*9525SPavel.Potoplyak@Sun.COM 		    real_name, NULL) < 0) {
10990Sstevel@tonic-gate 			PERROR("volrmmount exec failed");
11002160Szk194757 			/* Turn off the privileges */
11012160Szk194757 			(void) __priv_bracket(PRIV_OFF);
11020Sstevel@tonic-gate 			exit(-1);
11030Sstevel@tonic-gate 		}
11040Sstevel@tonic-gate 	} else if (waitpid(pid, &rval, 0) == pid) {
11050Sstevel@tonic-gate 		if (WIFEXITED(rval)) {
11060Sstevel@tonic-gate 			if (WEXITSTATUS(rval) == 0) {
11070Sstevel@tonic-gate 				DPRINTF("volrmmount: Success\n");
11080Sstevel@tonic-gate 				return (1);
11090Sstevel@tonic-gate 			}
11100Sstevel@tonic-gate 		}
11110Sstevel@tonic-gate 	}
11120Sstevel@tonic-gate 	return (-1);
11130Sstevel@tonic-gate }
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate int
find_device(int defer,char * tmpstr)11160Sstevel@tonic-gate find_device(int defer, char *tmpstr)
11170Sstevel@tonic-gate {
11180Sstevel@tonic-gate 	DIR *dir;
11190Sstevel@tonic-gate 	struct dirent *dirent;
11200Sstevel@tonic-gate 	char sdev[PATH_MAX], dev[PATH_MAX], *pname;
11210Sstevel@tonic-gate 	device_t *t_dev;
11223005Sphitran 	int removable = 0;
11233005Sphitran 	int device_type = 0;
11243005Sphitran 	int hotpluggable = 0;
11250Sstevel@tonic-gate 	struct dk_minfo mediainfo;
11260Sstevel@tonic-gate 	static int found = 0;
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate 	dir = opendir("/dev/rdsk");
11290Sstevel@tonic-gate 	if (dir == NULL)
11300Sstevel@tonic-gate 		return (-1);
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate 	total_devices_found = 0;
11330Sstevel@tonic-gate 	while ((dirent = readdir(dir)) != NULL) {
11340Sstevel@tonic-gate 		if (dirent->d_name[0] == '.') {
11350Sstevel@tonic-gate 			continue;
11360Sstevel@tonic-gate 		}
11370Sstevel@tonic-gate 		(void) snprintf(sdev, PATH_MAX, "/dev/rdsk/%s",
11380Sstevel@tonic-gate 		    dirent->d_name);
11390Sstevel@tonic-gate #ifdef sparc
11400Sstevel@tonic-gate 		if (!strstr(sdev, "s2")) {
11410Sstevel@tonic-gate 			continue;
11420Sstevel@tonic-gate 		}
11430Sstevel@tonic-gate #else /* x86 */
11440Sstevel@tonic-gate 		if (vol_running) {
11450Sstevel@tonic-gate 			if (!(strstr(sdev, "s2") || strstr(sdev, "p0"))) {
11460Sstevel@tonic-gate 				continue;
11470Sstevel@tonic-gate 			}
11480Sstevel@tonic-gate 		} else {
11490Sstevel@tonic-gate 			if (!strstr(sdev, "p0")) {
11500Sstevel@tonic-gate 				continue;
11510Sstevel@tonic-gate 			}
11520Sstevel@tonic-gate 		}
11530Sstevel@tonic-gate #endif
11540Sstevel@tonic-gate 		if (!lookup_device(sdev, dev)) {
11550Sstevel@tonic-gate 			continue;
11560Sstevel@tonic-gate 		}
11570Sstevel@tonic-gate 		if ((t_dev = get_device(NULL, dev)) == NULL) {
11580Sstevel@tonic-gate 			continue;
11590Sstevel@tonic-gate 		}
11600Sstevel@tonic-gate 		total_devices_found++;
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate 		if ((!defer) && !found) {
11630Sstevel@tonic-gate 			char *sn, *tmpbuf;
11640Sstevel@tonic-gate 			/*
11650Sstevel@tonic-gate 			 * dev_name is an optional command line input.
11660Sstevel@tonic-gate 			 */
11670Sstevel@tonic-gate 			if (dev_name) {
11680Sstevel@tonic-gate 				if (strstr(dirent->d_name, tmpstr)) {
11690Sstevel@tonic-gate 					found = 1;
11700Sstevel@tonic-gate 				} else if (!vol_running) {
11710Sstevel@tonic-gate 					continue;
11720Sstevel@tonic-gate 				}
11730Sstevel@tonic-gate 			}
11740Sstevel@tonic-gate 			/*
11750Sstevel@tonic-gate 			 * volmgt_symname() returns NULL if the device
11760Sstevel@tonic-gate 			 * is not managed by volmgt.
11770Sstevel@tonic-gate 			 */
11780Sstevel@tonic-gate 			sn = volmgt_symname(sdev);
11790Sstevel@tonic-gate 
11800Sstevel@tonic-gate 			if (vol_running && (sn != NULL)) {
11810Sstevel@tonic-gate 				if (strstr(sn, "dev") == NULL) {
11820Sstevel@tonic-gate 					tmpbuf = (char *)my_zalloc(PATH_MAX);
11830Sstevel@tonic-gate 					(void) strcpy(tmpbuf,
11840Sstevel@tonic-gate 					    "/vol/dev/aliases/");
11850Sstevel@tonic-gate 					(void) strcat(tmpbuf, sn);
11860Sstevel@tonic-gate 					free(sn);
11870Sstevel@tonic-gate 					sn = tmpbuf;
11880Sstevel@tonic-gate 				}
11890Sstevel@tonic-gate 				if (dev_name && !found) {
11900Sstevel@tonic-gate 					if (!strstr(tmpbuf, tmpstr)) {
11910Sstevel@tonic-gate 						continue;
11920Sstevel@tonic-gate 					} else {
11930Sstevel@tonic-gate 						found = 1;
11940Sstevel@tonic-gate 					}
11950Sstevel@tonic-gate 				}
11960Sstevel@tonic-gate 			}
11970Sstevel@tonic-gate 
11980Sstevel@tonic-gate 			/*
11990Sstevel@tonic-gate 			 * Get device type information for CD/DVD devices.
12000Sstevel@tonic-gate 			 */
12010Sstevel@tonic-gate 			if (is_cd(dev)) {
12020Sstevel@tonic-gate 				if (check_device(t_dev,
12030Sstevel@tonic-gate 				    CHECK_DEVICE_IS_DVD_WRITABLE)) {
12040Sstevel@tonic-gate 					device_type = DK_DVDR;
12050Sstevel@tonic-gate 				} else if (check_device(t_dev,
12060Sstevel@tonic-gate 				    CHECK_DEVICE_IS_DVD_READABLE)) {
12070Sstevel@tonic-gate 					device_type = DK_DVDROM;
12080Sstevel@tonic-gate 				} else if (check_device(t_dev,
12090Sstevel@tonic-gate 				    CHECK_DEVICE_IS_CD_WRITABLE)) {
12100Sstevel@tonic-gate 					device_type = DK_CDR;
12110Sstevel@tonic-gate 				} else {
12120Sstevel@tonic-gate 					device_type = DK_CDROM;
12130Sstevel@tonic-gate 				}
12140Sstevel@tonic-gate 			} else {
12150Sstevel@tonic-gate 				device_type = ioctl(t_dev->d_fd,
12160Sstevel@tonic-gate 				    DKIOCGMEDIAINFO, &mediainfo);
12170Sstevel@tonic-gate 				if (device_type < 0)
12180Sstevel@tonic-gate 					device_type = 0;
12190Sstevel@tonic-gate 				else
12200Sstevel@tonic-gate 					device_type = mediainfo.dki_media_type;
12210Sstevel@tonic-gate 			}
12220Sstevel@tonic-gate 
12233005Sphitran 			if (!ioctl(t_dev->d_fd, DKIOCREMOVABLE, &removable) &&
12243005Sphitran 			    !ioctl(t_dev->d_fd, DKIOCHOTPLUGGABLE,
12253005Sphitran 			    &hotpluggable)) {
12263005Sphitran 				if (removable || hotpluggable) {
12270Sstevel@tonic-gate 					removable_found++;
12280Sstevel@tonic-gate 					pname = get_physical_name(sdev);
12290Sstevel@tonic-gate 					if (sn) {
12300Sstevel@tonic-gate 						(void) printf("  %4d. "
12310Sstevel@tonic-gate 						    "Volmgt Node: %s\n",
12320Sstevel@tonic-gate 						    removable_found, sn);
12330Sstevel@tonic-gate 						(void) printf("        "
12340Sstevel@tonic-gate 						    "Logical Node: %s\n", sdev);
12350Sstevel@tonic-gate 						(void) printf("        "
12360Sstevel@tonic-gate 						    "Physical Node: %s\n",
12370Sstevel@tonic-gate 						    pname);
12380Sstevel@tonic-gate 					} else {
12390Sstevel@tonic-gate 						(void) printf("  %4d. "
12400Sstevel@tonic-gate 						    "Logical Node: %s\n",
12410Sstevel@tonic-gate 						    removable_found, sdev);
12420Sstevel@tonic-gate 						(void) printf("        "
12430Sstevel@tonic-gate 						    "Physical Node: %s\n",
12440Sstevel@tonic-gate 						    pname);
12450Sstevel@tonic-gate 					}
12460Sstevel@tonic-gate 					(void) printf("        Connected "
12470Sstevel@tonic-gate 					    "Device: %-8.8s %-16.16s "
12480Sstevel@tonic-gate 					    "%-4.4s\n",
12490Sstevel@tonic-gate 					    &t_dev->d_inq[8],
12500Sstevel@tonic-gate 					    &t_dev->d_inq[16],
12510Sstevel@tonic-gate 					    &t_dev->d_inq[32]);
12520Sstevel@tonic-gate 					(void) printf("        Device "
12530Sstevel@tonic-gate 					    "Type: ");
12540Sstevel@tonic-gate 				} else
12550Sstevel@tonic-gate 					continue;
12560Sstevel@tonic-gate 			} else
12570Sstevel@tonic-gate 				continue;
12580Sstevel@tonic-gate 
12590Sstevel@tonic-gate 			switch (device_type) {
12600Sstevel@tonic-gate 				case DK_CDROM:
12610Sstevel@tonic-gate 					(void) printf("CD Reader\n");
12620Sstevel@tonic-gate 					break;
12630Sstevel@tonic-gate 				case DK_CDR:
12640Sstevel@tonic-gate 				case DK_CDRW:
12650Sstevel@tonic-gate 					(void) printf("CD Reader/Writer\n");
12660Sstevel@tonic-gate 					break;
12670Sstevel@tonic-gate 				case DK_DVDROM:
12680Sstevel@tonic-gate 					(void) printf("DVD Reader\n");
12690Sstevel@tonic-gate 					break;
12700Sstevel@tonic-gate 				case DK_DVDR:
12710Sstevel@tonic-gate 				case DK_DVDRAM:
12720Sstevel@tonic-gate 					(void) printf("DVD Reader/Writer\n");
12730Sstevel@tonic-gate 					break;
12740Sstevel@tonic-gate 				case DK_FIXED_DISK:
12750Sstevel@tonic-gate 					if (strstr((const char *)
12760Sstevel@tonic-gate 					    &t_dev->d_inq[16], "FD") ||
12770Sstevel@tonic-gate 					    strstr((const char *)
12780Sstevel@tonic-gate 					    &t_dev->d_inq[16], "LS-120"))
12790Sstevel@tonic-gate 						(void) printf("Floppy "
12800Sstevel@tonic-gate 						    "drive\n");
12810Sstevel@tonic-gate 					else
12820Sstevel@tonic-gate 						(void) printf("Removable\n");
12830Sstevel@tonic-gate 					break;
12840Sstevel@tonic-gate 				case DK_FLOPPY:
12850Sstevel@tonic-gate 					(void) printf("Floppy drive\n");
12860Sstevel@tonic-gate 					break;
12870Sstevel@tonic-gate 				case DK_ZIP:
12880Sstevel@tonic-gate 					(void) printf("Zip drive\n");
12890Sstevel@tonic-gate 					break;
12900Sstevel@tonic-gate 				case DK_JAZ:
12910Sstevel@tonic-gate 					(void) printf("Jaz drive\n");
12920Sstevel@tonic-gate 					break;
12930Sstevel@tonic-gate 				default:
12940Sstevel@tonic-gate 					(void) printf("<Unknown>\n");
12950Sstevel@tonic-gate 					DPRINTF1("\t   %d\n", device_type);
12960Sstevel@tonic-gate 					break;
12970Sstevel@tonic-gate 			}
12980Sstevel@tonic-gate 			get_media_info(t_dev, sdev, pname, sn);
12990Sstevel@tonic-gate 		}
13000Sstevel@tonic-gate 		fini_device(t_dev);
13010Sstevel@tonic-gate 	}
13020Sstevel@tonic-gate 
13030Sstevel@tonic-gate 	(void) closedir(dir);
13040Sstevel@tonic-gate 	return (removable_found);
13050Sstevel@tonic-gate }
13060Sstevel@tonic-gate 
13070Sstevel@tonic-gate /*
13080Sstevel@tonic-gate  * Returns a device_t handle for a node returned by lookup_device()
13090Sstevel@tonic-gate  * and takes the user supplied name and stores it inside the node.
13100Sstevel@tonic-gate  */
13110Sstevel@tonic-gate static device_t *
get_device(char * user_supplied,char * node)13120Sstevel@tonic-gate get_device(char *user_supplied, char *node)
13130Sstevel@tonic-gate {
13140Sstevel@tonic-gate 	device_t *dev;
13150Sstevel@tonic-gate 	int fd;
13160Sstevel@tonic-gate 	char devnode[PATH_MAX];
13170Sstevel@tonic-gate 	int size;
13180Sstevel@tonic-gate 
13190Sstevel@tonic-gate 	/*
13200Sstevel@tonic-gate 	 * we need to resolve any link paths to avoid fake files
13210Sstevel@tonic-gate 	 * such as /dev/rdsk/../../export/file.
13220Sstevel@tonic-gate 	 */
13230Sstevel@tonic-gate 	size = resolvepath(node, devnode, PATH_MAX);
13240Sstevel@tonic-gate 	if ((size <= 0) || (size >= (PATH_MAX - 1)))
13250Sstevel@tonic-gate 		return (NULL);
13260Sstevel@tonic-gate 
13270Sstevel@tonic-gate 	/* resolvepath may not return a null terminated string */
13280Sstevel@tonic-gate 	devnode[size] = '\0';
13290Sstevel@tonic-gate 
13300Sstevel@tonic-gate 
13310Sstevel@tonic-gate 	/* the device node must be in /devices/ or /vol/dev/rdsk */
13320Sstevel@tonic-gate 
13330Sstevel@tonic-gate 	if ((strncmp(devnode, "/devices/", 9) != 0) &&
13340Sstevel@tonic-gate 	    (strncmp(devnode, "/vol/dev/rdsk", 13) != 0))
13350Sstevel@tonic-gate 		return (NULL);
13360Sstevel@tonic-gate 
13372160Szk194757 	/* Turn on the privileges. */
13382160Szk194757 	(void) __priv_bracket(PRIV_ON);
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate 	/*
13410Sstevel@tonic-gate 	 * Since we are currently running with the user euid it is
13420Sstevel@tonic-gate 	 * safe to try to open the file without checking access.
13430Sstevel@tonic-gate 	 */
13440Sstevel@tonic-gate 
13450Sstevel@tonic-gate 	fd = open(devnode, O_RDONLY|O_NDELAY);
13460Sstevel@tonic-gate 
13472160Szk194757 	/* Turn off the privileges. */
13482160Szk194757 	(void) __priv_bracket(PRIV_OFF);
13490Sstevel@tonic-gate 
13500Sstevel@tonic-gate 	if (fd < 0) {
13510Sstevel@tonic-gate 		return (NULL);
13520Sstevel@tonic-gate 	}
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 	dev = (device_t *)my_zalloc(sizeof (device_t));
13550Sstevel@tonic-gate 
13560Sstevel@tonic-gate 	dev->d_node = (char *)my_zalloc(strlen(devnode) + 1);
13570Sstevel@tonic-gate 	(void) strcpy(dev->d_node, devnode);
13580Sstevel@tonic-gate 
13590Sstevel@tonic-gate 	dev->d_fd = fd;
13600Sstevel@tonic-gate 
13610Sstevel@tonic-gate 	dev->d_inq = (uchar_t *)my_zalloc(INQUIRY_DATA_LENGTH);
13620Sstevel@tonic-gate 
13632160Szk194757 	/* Turn on privileges. */
13642160Szk194757 	(void) __priv_bracket(PRIV_ON);
13650Sstevel@tonic-gate 	if (!inquiry(fd, dev->d_inq)) {
13660Sstevel@tonic-gate 		DPRINTF1("USCSI ioctl failed %d\n",
13670Sstevel@tonic-gate 		    uscsi_error);
13680Sstevel@tonic-gate 		free(dev->d_inq);
13690Sstevel@tonic-gate 		free(dev->d_node);
13700Sstevel@tonic-gate 		(void) close(dev->d_fd);
13710Sstevel@tonic-gate 		free(dev);
13722160Szk194757 		/* Turn off privileges. */
13732160Szk194757 		(void) __priv_bracket(PRIV_OFF);
13740Sstevel@tonic-gate 		return (NULL);
13750Sstevel@tonic-gate 	}
13762160Szk194757 	/* Turn off privileges. */
13772160Szk194757 	(void) __priv_bracket(PRIV_OFF);
13780Sstevel@tonic-gate 
13790Sstevel@tonic-gate 	if (user_supplied) {
13800Sstevel@tonic-gate 		dev->d_name = (char *)my_zalloc(strlen(user_supplied) + 1);
13810Sstevel@tonic-gate 		(void) strcpy(dev->d_name, user_supplied);
13820Sstevel@tonic-gate 	}
13830Sstevel@tonic-gate 	return (dev);
13840Sstevel@tonic-gate }
13850Sstevel@tonic-gate 
13860Sstevel@tonic-gate /*
13870Sstevel@tonic-gate  * Check for device specific characteristics.
13880Sstevel@tonic-gate  */
13890Sstevel@tonic-gate int
check_device(device_t * dev,int cond)13900Sstevel@tonic-gate check_device(device_t *dev, int cond)
13910Sstevel@tonic-gate {
13920Sstevel@tonic-gate 	uchar_t page_code[4];
13930Sstevel@tonic-gate 
13940Sstevel@tonic-gate 	/* Look at the capabilities page for this information */
13950Sstevel@tonic-gate 	if (cond & CHECK_DEVICE_IS_CD_WRITABLE) {
13960Sstevel@tonic-gate 		if (get_mode_page(dev->d_fd, 0x2a, 0, 4, page_code) &&
13970Sstevel@tonic-gate 		    (page_code[3] & 1)) {
13980Sstevel@tonic-gate 			return (1);
13990Sstevel@tonic-gate 		}
14000Sstevel@tonic-gate 	}
14010Sstevel@tonic-gate 
14020Sstevel@tonic-gate 	if (cond & CHECK_DEVICE_IS_DVD_WRITABLE) {
14030Sstevel@tonic-gate 		if (get_mode_page(dev->d_fd, 0x2a, 0, 4, page_code) &&
14040Sstevel@tonic-gate 		    (page_code[3] & 0x10)) {
14050Sstevel@tonic-gate 			return (1);
14060Sstevel@tonic-gate 		}
14070Sstevel@tonic-gate 	}
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 	if (cond & CHECK_DEVICE_IS_DVD_READABLE) {
14100Sstevel@tonic-gate 		if (get_mode_page(dev->d_fd, 0x2a, 0, 4, page_code) &&
14110Sstevel@tonic-gate 		    (page_code[2] & 0x8)) {
14120Sstevel@tonic-gate 			return (1);
14130Sstevel@tonic-gate 		}
14140Sstevel@tonic-gate 	}
14150Sstevel@tonic-gate 
14160Sstevel@tonic-gate 	return (0);
14170Sstevel@tonic-gate }
14180Sstevel@tonic-gate 
14190Sstevel@tonic-gate /*
14200Sstevel@tonic-gate  * Builds an open()able device path from a user supplied node which can be
14210Sstevel@tonic-gate  * of the * form of /dev/[r]dsk/cxtxdx[sx] or cxtxdx[sx] or volmgt-name like
14220Sstevel@tonic-gate  * cdrom[n].
14230Sstevel@tonic-gate  * Returns the path found in 'found' and returns 1. Otherwise returns 0.
14240Sstevel@tonic-gate  */
14250Sstevel@tonic-gate int
lookup_device(char * supplied,char * found)14260Sstevel@tonic-gate lookup_device(char *supplied, char *found)
14270Sstevel@tonic-gate {
14280Sstevel@tonic-gate 	struct stat statbuf;
14290Sstevel@tonic-gate 	int fd;
14300Sstevel@tonic-gate 	char tmpstr[PATH_MAX];
14310Sstevel@tonic-gate 
14322160Szk194757 	/* Turn on privileges */
14332160Szk194757 	(void) __priv_bracket(PRIV_ON);
14340Sstevel@tonic-gate 
14350Sstevel@tonic-gate 	/* If everything is fine and proper, no need to analyze */
1436871Scasper 	if ((stat(supplied, &statbuf) == 0) && S_ISCHR(statbuf.st_mode) &&
14370Sstevel@tonic-gate 	    ((fd = open(supplied, O_RDONLY|O_NDELAY)) >= 0)) {
14380Sstevel@tonic-gate 		(void) close(fd);
14390Sstevel@tonic-gate 		(void) strlcpy(found, supplied, PATH_MAX);
14402160Szk194757 		/* Turn off privilege */
14412160Szk194757 		(void) __priv_bracket(PRIV_OFF);
14420Sstevel@tonic-gate 		return (1);
14430Sstevel@tonic-gate 	}
14440Sstevel@tonic-gate 
14452160Szk194757 	/* Turn off privileges. */
14462160Szk194757 	(void) __priv_bracket(PRIV_OFF);
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate 	if (strncmp(supplied, "/dev/rdsk/", 10) == 0)
14490Sstevel@tonic-gate 		return (vol_lookup(supplied, found));
14500Sstevel@tonic-gate 	if (strncmp(supplied, "/dev/dsk/", 9) == 0) {
14510Sstevel@tonic-gate 		(void) snprintf(tmpstr, PATH_MAX, "/dev/rdsk/%s",
14520Sstevel@tonic-gate 		    (char *)strrchr(supplied, '/'));
14530Sstevel@tonic-gate 
14540Sstevel@tonic-gate 		if ((fd = open(tmpstr, O_RDONLY|O_NDELAY)) >= 0) {
14550Sstevel@tonic-gate 			(void) close(fd);
14560Sstevel@tonic-gate 			(void) strlcpy(found, supplied, PATH_MAX);
14570Sstevel@tonic-gate 			return (1);
14580Sstevel@tonic-gate 		}
14590Sstevel@tonic-gate 		if ((access(tmpstr, F_OK) == 0) && vol_running)
14600Sstevel@tonic-gate 			return (vol_lookup(tmpstr, found));
14610Sstevel@tonic-gate 		else
14620Sstevel@tonic-gate 			return (0);
14630Sstevel@tonic-gate 	}
14640Sstevel@tonic-gate 	if ((strncmp(supplied, "cdrom", 5) != 0) &&
14650Sstevel@tonic-gate 	    (strlen(supplied) < 32)) {
14660Sstevel@tonic-gate 		(void) snprintf(tmpstr, sizeof (tmpstr), "/dev/rdsk/%s",
14670Sstevel@tonic-gate 		    supplied);
14680Sstevel@tonic-gate 		if (access(tmpstr, F_OK) < 0) {
14690Sstevel@tonic-gate 			(void) strcat(tmpstr, "s2");
14700Sstevel@tonic-gate 		}
14710Sstevel@tonic-gate 		if ((fd = open(tmpstr, O_RDONLY|O_NDELAY)) >= 0) {
14720Sstevel@tonic-gate 			(void) close(fd);
14730Sstevel@tonic-gate 			(void) strlcpy(found, tmpstr, PATH_MAX);
14740Sstevel@tonic-gate 			return (1);
14750Sstevel@tonic-gate 		}
14760Sstevel@tonic-gate 		if ((access(tmpstr, F_OK) == 0) && vol_running)
14770Sstevel@tonic-gate 			return (vol_lookup(tmpstr, found));
14780Sstevel@tonic-gate 	}
14790Sstevel@tonic-gate 	return (vol_name_to_dev_node(supplied, found));
14800Sstevel@tonic-gate }
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate int
is_cd(char * node)14830Sstevel@tonic-gate is_cd(char *node)
14840Sstevel@tonic-gate {
14850Sstevel@tonic-gate 	int fd;
14860Sstevel@tonic-gate 	struct dk_cinfo cinfo;
14870Sstevel@tonic-gate 
14880Sstevel@tonic-gate 	fd = open(node, O_RDONLY|O_NDELAY);
14890Sstevel@tonic-gate 	if (fd < 0)
14900Sstevel@tonic-gate 		return (0);
14910Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &cinfo) < 0) {
14920Sstevel@tonic-gate 		(void) close(fd);
14930Sstevel@tonic-gate 		return (0);
14940Sstevel@tonic-gate 	}
14950Sstevel@tonic-gate 	if (cinfo.dki_ctype != DKC_CDROM)
14960Sstevel@tonic-gate 		return (0);
14970Sstevel@tonic-gate 	return (1);
14980Sstevel@tonic-gate }
14990Sstevel@tonic-gate 
15000Sstevel@tonic-gate void
print_header(void)15010Sstevel@tonic-gate print_header(void)
15020Sstevel@tonic-gate {
15030Sstevel@tonic-gate 	/* l10n_NOTE : Column spacing should be kept same */
15040Sstevel@tonic-gate 	(void) printf(gettext("    Node 		       "
15050Sstevel@tonic-gate 	    "Connected Device"));
15060Sstevel@tonic-gate 	/* l10n_NOTE : Column spacing should be kept same */
15070Sstevel@tonic-gate 	(void) printf(gettext(" 		Device type\n"));
15080Sstevel@tonic-gate 	(void) printf(
15090Sstevel@tonic-gate 	    "---------------------------+---------------------------");
15100Sstevel@tonic-gate 	(void) printf("-----+----------------\n");
15110Sstevel@tonic-gate }
15120Sstevel@tonic-gate 
15130Sstevel@tonic-gate void
print_divider(void)15140Sstevel@tonic-gate print_divider(void)
15150Sstevel@tonic-gate {
15160Sstevel@tonic-gate 	(void) printf(
15170Sstevel@tonic-gate 	    "---------------------------+---------------------------");
15180Sstevel@tonic-gate 	(void) printf("-----+----------------\n");
15190Sstevel@tonic-gate }
15200Sstevel@tonic-gate 
15210Sstevel@tonic-gate static void
fini_device(device_t * dev)15220Sstevel@tonic-gate fini_device(device_t *dev)
15230Sstevel@tonic-gate {
15240Sstevel@tonic-gate 	free(dev->d_inq);
15250Sstevel@tonic-gate 	free(dev->d_node);
15260Sstevel@tonic-gate 	(void) close(dev->d_fd);
15270Sstevel@tonic-gate 	if (dev->d_name)
15280Sstevel@tonic-gate 		free(dev->d_name);
15290Sstevel@tonic-gate 	free(dev);
15300Sstevel@tonic-gate }
15310Sstevel@tonic-gate 
15320Sstevel@tonic-gate void *
my_zalloc(size_t size)15330Sstevel@tonic-gate my_zalloc(size_t size)
15340Sstevel@tonic-gate {
15350Sstevel@tonic-gate 	void *ret;
15360Sstevel@tonic-gate 
15370Sstevel@tonic-gate 	ret = malloc(size);
15380Sstevel@tonic-gate 	if (ret == NULL) {
15390Sstevel@tonic-gate 
15400Sstevel@tonic-gate 		/* Lets wait a sec. and try again */
15410Sstevel@tonic-gate 		if (errno == EAGAIN) {
15420Sstevel@tonic-gate 			(void) sleep(1);
15430Sstevel@tonic-gate 			ret = malloc(size);
15440Sstevel@tonic-gate 		}
15450Sstevel@tonic-gate 
15460Sstevel@tonic-gate 		if (ret == NULL) {
15470Sstevel@tonic-gate 			(void) err_msg("%s\n", gettext(strerror(errno)));
15480Sstevel@tonic-gate 			(void) err_msg(gettext(
15490Sstevel@tonic-gate 			    "Memory allocation failure, Exiting...\n"));
15500Sstevel@tonic-gate 			exit(1);
15510Sstevel@tonic-gate 		}
15520Sstevel@tonic-gate 	}
15530Sstevel@tonic-gate 	(void) memset(ret, 0, size);
15540Sstevel@tonic-gate 	return (ret);
15550Sstevel@tonic-gate }
15560Sstevel@tonic-gate 
15570Sstevel@tonic-gate static int
vol_name_to_dev_node(char * vname,char * found)15580Sstevel@tonic-gate vol_name_to_dev_node(char *vname, char *found)
15590Sstevel@tonic-gate {
15600Sstevel@tonic-gate 	struct stat statbuf;
15610Sstevel@tonic-gate 	char *p1;
15620Sstevel@tonic-gate 	int i;
15630Sstevel@tonic-gate 
15640Sstevel@tonic-gate 	if (vname == NULL)
15650Sstevel@tonic-gate 		return (0);
15660Sstevel@tonic-gate 	if (vol_running)
15670Sstevel@tonic-gate 		(void) volmgt_check(vname);
15680Sstevel@tonic-gate 	p1 = media_findname(vname);
15690Sstevel@tonic-gate 	if (p1 == NULL)
15700Sstevel@tonic-gate 		return (0);
15710Sstevel@tonic-gate 	if (stat(p1, &statbuf) < 0) {
15720Sstevel@tonic-gate 		free(p1);
15730Sstevel@tonic-gate 		return (0);
15740Sstevel@tonic-gate 	}
1575871Scasper 	if (S_ISDIR(statbuf.st_mode)) {
15760Sstevel@tonic-gate 		for (i = 0; i < 16; i++) {
15770Sstevel@tonic-gate 			(void) snprintf(found, PATH_MAX, "%s/s%d", p1, i);
15780Sstevel@tonic-gate 			if (access(found, F_OK) >= 0)
15790Sstevel@tonic-gate 				break;
15800Sstevel@tonic-gate 		}
15810Sstevel@tonic-gate 		if (i == 16) {
15820Sstevel@tonic-gate 			free(p1);
15830Sstevel@tonic-gate 			return (0);
15840Sstevel@tonic-gate 		}
15850Sstevel@tonic-gate 	} else {
15860Sstevel@tonic-gate 		(void) strlcpy(found, p1, PATH_MAX);
15870Sstevel@tonic-gate 	}
15880Sstevel@tonic-gate 	free(p1);
15890Sstevel@tonic-gate 	return (1);
15900Sstevel@tonic-gate }
15910Sstevel@tonic-gate 
15920Sstevel@tonic-gate /*
15930Sstevel@tonic-gate  * Searches for volume manager's equivalent char device for the
15940Sstevel@tonic-gate  * supplied pathname which is of the form of /dev/rdsk/cxtxdxsx
15950Sstevel@tonic-gate  */
15960Sstevel@tonic-gate static int
vol_lookup(char * supplied,char * found)15970Sstevel@tonic-gate vol_lookup(char *supplied, char *found)
15980Sstevel@tonic-gate {
15990Sstevel@tonic-gate 	char tmpstr[PATH_MAX], tmpstr1[PATH_MAX], *p;
16000Sstevel@tonic-gate 	int i, ret;
16010Sstevel@tonic-gate 
16020Sstevel@tonic-gate 	(void) strlcpy(tmpstr, supplied, PATH_MAX);
16030Sstevel@tonic-gate 	if ((p = volmgt_symname(tmpstr)) == NULL) {
16040Sstevel@tonic-gate 		if (strstr(tmpstr, "s2") != NULL) {
16050Sstevel@tonic-gate 			*((char *)(strrchr(tmpstr, 's') + 1)) = 0;
16060Sstevel@tonic-gate 			for (i = 0; i < 16; i++) {
16070Sstevel@tonic-gate 				(void) snprintf(tmpstr1, PATH_MAX, "%s%d",
16080Sstevel@tonic-gate 				    tmpstr, i);
16090Sstevel@tonic-gate 				if ((p = volmgt_symname(tmpstr1)) != NULL)
16100Sstevel@tonic-gate 					break;
16110Sstevel@tonic-gate 			}
16120Sstevel@tonic-gate 		} else if (strstr(tmpstr, "p0") != NULL) {
16130Sstevel@tonic-gate 			*((char *)(strrchr(tmpstr, 'p') + 1)) = 0;
16140Sstevel@tonic-gate 			for (i = 0; i < 5; i++) {
16150Sstevel@tonic-gate 				(void) snprintf(tmpstr1, PATH_MAX, "%s%d",
1616*9525SPavel.Potoplyak@Sun.COM 				    tmpstr, i);
16170Sstevel@tonic-gate 				if ((p = volmgt_symname(tmpstr1)) != NULL)
16180Sstevel@tonic-gate 					break;
16190Sstevel@tonic-gate 			}
16200Sstevel@tonic-gate 		} else
16210Sstevel@tonic-gate 			return (0);
16220Sstevel@tonic-gate 		if (p == NULL)
16230Sstevel@tonic-gate 			return (0);
16240Sstevel@tonic-gate 	}
16250Sstevel@tonic-gate 
16260Sstevel@tonic-gate 	ret = vol_name_to_dev_node(p, found);
16270Sstevel@tonic-gate 	free(p);
16280Sstevel@tonic-gate 	return (ret);
16290Sstevel@tonic-gate }
16300Sstevel@tonic-gate 
16310Sstevel@tonic-gate /*PRINTFLIKE1*/
16320Sstevel@tonic-gate void
err_msg(char * fmt,...)16330Sstevel@tonic-gate err_msg(char *fmt, ...)
16340Sstevel@tonic-gate {
16350Sstevel@tonic-gate 	va_list ap;
16360Sstevel@tonic-gate 
16370Sstevel@tonic-gate 	va_start(ap, fmt);
16380Sstevel@tonic-gate 	(void) vfprintf(stderr, fmt, ap);
16390Sstevel@tonic-gate 	va_end(ap);
16400Sstevel@tonic-gate }
16410Sstevel@tonic-gate 
16420Sstevel@tonic-gate int
inquiry(int fd,uchar_t * inq)16430Sstevel@tonic-gate inquiry(int fd, uchar_t *inq)
16440Sstevel@tonic-gate {
16450Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
16460Sstevel@tonic-gate 
16470Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
16480Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
16490Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
16500Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = INQUIRY_CMD;
16510Sstevel@tonic-gate 	scmd->uscsi_cdb[4] = INQUIRY_DATA_LENGTH;
16520Sstevel@tonic-gate 	scmd->uscsi_cdblen = 6;
16530Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)inq;
16540Sstevel@tonic-gate 	scmd->uscsi_buflen = INQUIRY_DATA_LENGTH;
16550Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
16560Sstevel@tonic-gate 		return (0);
16570Sstevel@tonic-gate 	return (1);
16580Sstevel@tonic-gate }
16590Sstevel@tonic-gate 
16600Sstevel@tonic-gate struct uscsi_cmd *
get_uscsi_cmd(void)16610Sstevel@tonic-gate get_uscsi_cmd(void)
16620Sstevel@tonic-gate {
16630Sstevel@tonic-gate 	(void) memset(&uscmd, 0, sizeof (uscmd));
16640Sstevel@tonic-gate 	(void) memset(ucdb, 0, 16);
16650Sstevel@tonic-gate 	uscmd.uscsi_cdb = ucdb;
16660Sstevel@tonic-gate 	return (&uscmd);
16670Sstevel@tonic-gate }
16680Sstevel@tonic-gate 
16690Sstevel@tonic-gate int
uscsi(int fd,struct uscsi_cmd * scmd)16700Sstevel@tonic-gate uscsi(int fd, struct uscsi_cmd *scmd)
16710Sstevel@tonic-gate {
16720Sstevel@tonic-gate 	int ret, global_rqsense;
16730Sstevel@tonic-gate 	int retries, max_retries = 5;
16740Sstevel@tonic-gate 	int i;
16750Sstevel@tonic-gate 
16760Sstevel@tonic-gate 	/* set up for request sense extensions */
16770Sstevel@tonic-gate 	if (!(scmd->uscsi_flags & USCSI_RQENABLE)) {
16780Sstevel@tonic-gate 		scmd->uscsi_flags |= USCSI_RQENABLE;
16790Sstevel@tonic-gate 		scmd->uscsi_rqlen = RQBUFLEN;
16800Sstevel@tonic-gate 		scmd->uscsi_rqbuf = rqbuf;
16810Sstevel@tonic-gate 		global_rqsense = 1;
16820Sstevel@tonic-gate 	} else {
16830Sstevel@tonic-gate 		global_rqsense = 0;
16840Sstevel@tonic-gate 	}
16850Sstevel@tonic-gate 
16860Sstevel@tonic-gate 	/*
16870Sstevel@tonic-gate 	 * The device may be busy or slow and fail with a not ready status.
16880Sstevel@tonic-gate 	 * we'll allow a limited number of retries to give the drive time
16890Sstevel@tonic-gate 	 * to recover.
16900Sstevel@tonic-gate 	 */
16910Sstevel@tonic-gate 	for (retries = 0; retries < max_retries; retries++) {
16920Sstevel@tonic-gate 
16930Sstevel@tonic-gate 		scmd->uscsi_status = 0;
16940Sstevel@tonic-gate 
16950Sstevel@tonic-gate 		if (global_rqsense)
16960Sstevel@tonic-gate 			(void) memset(rqbuf, 0, RQBUFLEN);
16970Sstevel@tonic-gate 
16980Sstevel@tonic-gate 		DPRINTF("cmd:[");
16990Sstevel@tonic-gate 		for (i = 0; i < scmd->uscsi_cdblen; i++)
17000Sstevel@tonic-gate 			DPRINTF1("0x%02x ",
17010Sstevel@tonic-gate 			    (uchar_t)scmd->uscsi_cdb[i]);
17020Sstevel@tonic-gate 		DPRINTF("]\n");
17030Sstevel@tonic-gate 
17040Sstevel@tonic-gate 		/*
17050Sstevel@tonic-gate 		 * We need to have root privledges in order to use
17060Sstevel@tonic-gate 		 * uscsi commands on the device.
17070Sstevel@tonic-gate 		 */
17080Sstevel@tonic-gate 
17090Sstevel@tonic-gate 		ret = ioctl(fd, USCSICMD, scmd);
17100Sstevel@tonic-gate 
17110Sstevel@tonic-gate 		/* maintain consistency in case of sgen */
17120Sstevel@tonic-gate 		if ((ret == 0) && (scmd->uscsi_status == 2)) {
17130Sstevel@tonic-gate 			ret = -1;
17140Sstevel@tonic-gate 			errno = EIO;
17150Sstevel@tonic-gate 		}
17160Sstevel@tonic-gate 
17170Sstevel@tonic-gate 		/* if error and extended request sense, retrieve errors */
17180Sstevel@tonic-gate 		if (global_rqsense && (ret < 0) && (scmd->uscsi_status == 2)) {
17190Sstevel@tonic-gate 			/*
17200Sstevel@tonic-gate 			 * The drive is not ready to recieve commands but
17210Sstevel@tonic-gate 			 * may be in the process of becoming ready.
17220Sstevel@tonic-gate 			 * sleep for a short time then retry command.
17230Sstevel@tonic-gate 			 * SENSE/ASC = 2/4 : not ready
17240Sstevel@tonic-gate 			 * ASCQ = 0  Not Reportable.
17250Sstevel@tonic-gate 			 * ASCQ = 1  Becoming ready.
17260Sstevel@tonic-gate 			 */
17270Sstevel@tonic-gate 			if ((SENSE_KEY(rqbuf) == 2) && (ASC(rqbuf) == 4) &&
17280Sstevel@tonic-gate 			    ((ASCQ(rqbuf) == 0) || (ASCQ(rqbuf) == 1))) {
17290Sstevel@tonic-gate 				total_retries++;
17300Sstevel@tonic-gate 				(void) sleep(3);
17310Sstevel@tonic-gate 				continue;
17320Sstevel@tonic-gate 			}
17330Sstevel@tonic-gate 
17340Sstevel@tonic-gate 			/*
17350Sstevel@tonic-gate 			 * Device is not ready to transmit or a device reset
17360Sstevel@tonic-gate 			 * has occurred. wait for a short period of time then
17370Sstevel@tonic-gate 			 * retry the command.
17380Sstevel@tonic-gate 			 */
17390Sstevel@tonic-gate 			if ((SENSE_KEY(rqbuf) == 6) && ((ASC(rqbuf) == 0x28) ||
17400Sstevel@tonic-gate 			    (ASC(rqbuf) == 0x29))) {
17410Sstevel@tonic-gate 				(void) sleep(3);
17420Sstevel@tonic-gate 				total_retries++;
17430Sstevel@tonic-gate 				continue;
17440Sstevel@tonic-gate 			}
17450Sstevel@tonic-gate 
17460Sstevel@tonic-gate 			DPRINTF3("cmd: 0x%02x ret:%i status:%02x ",
17470Sstevel@tonic-gate 			    (uchar_t)scmd->uscsi_cdb[0], ret,
17480Sstevel@tonic-gate 			    scmd->uscsi_status);
17490Sstevel@tonic-gate 			DPRINTF3(" sense: %02x ASC: %02x ASCQ:%02x\n",
17500Sstevel@tonic-gate 			    (uchar_t)SENSE_KEY(rqbuf),
17510Sstevel@tonic-gate 			    (uchar_t)ASC(rqbuf), (uchar_t)ASCQ(rqbuf));
17520Sstevel@tonic-gate 		}
17530Sstevel@tonic-gate 
17540Sstevel@tonic-gate 		/* no errors we'll return */
17550Sstevel@tonic-gate 		break;
17560Sstevel@tonic-gate 	}
17570Sstevel@tonic-gate 
17580Sstevel@tonic-gate 	/* store the error status for later debug printing */
17590Sstevel@tonic-gate 	if ((ret < 0) && (global_rqsense)) {
17600Sstevel@tonic-gate 		uscsi_status = scmd->uscsi_status;
17610Sstevel@tonic-gate 		rqstatus = scmd->uscsi_rqstatus;
17620Sstevel@tonic-gate 		rqresid = scmd->uscsi_rqresid;
17630Sstevel@tonic-gate 
17640Sstevel@tonic-gate 	}
17650Sstevel@tonic-gate 
17660Sstevel@tonic-gate 	DPRINTF1("total retries: %d\n", total_retries);
17670Sstevel@tonic-gate 
17680Sstevel@tonic-gate 	return (ret);
17690Sstevel@tonic-gate }
17700Sstevel@tonic-gate 
17710Sstevel@tonic-gate /*
17720Sstevel@tonic-gate  * will get the mode page only i.e. will strip off the header.
17730Sstevel@tonic-gate  */
17740Sstevel@tonic-gate int
get_mode_page(int fd,int page_no,int pc,int buf_len,uchar_t * buffer)17750Sstevel@tonic-gate get_mode_page(int fd, int page_no, int pc, int buf_len, uchar_t *buffer)
17760Sstevel@tonic-gate {
17770Sstevel@tonic-gate 	int ret;
17780Sstevel@tonic-gate 	uchar_t byte2, *buf;
17790Sstevel@tonic-gate 	uint_t header_len, page_len, copy_cnt;
17800Sstevel@tonic-gate 
17810Sstevel@tonic-gate 	byte2 = (uchar_t)(((pc << 6) & 0xC0) | (page_no & 0x3f));
17820Sstevel@tonic-gate 	buf = (uchar_t *)my_zalloc(256);
17830Sstevel@tonic-gate 
17840Sstevel@tonic-gate 	/* Ask 254 bytes only to make our IDE driver happy */
17850Sstevel@tonic-gate 	ret = mode_sense(fd, byte2, 1, 254, buf);
17860Sstevel@tonic-gate 	if (ret == 0) {
17870Sstevel@tonic-gate 		free(buf);
17880Sstevel@tonic-gate 		return (0);
17890Sstevel@tonic-gate 	}
17900Sstevel@tonic-gate 
17910Sstevel@tonic-gate 	header_len = 8 + read_scsi16(&buf[6]);
17920Sstevel@tonic-gate 	page_len = buf[header_len + 1] + 2;
17930Sstevel@tonic-gate 
17940Sstevel@tonic-gate 	copy_cnt = (page_len > buf_len) ? buf_len : page_len;
17950Sstevel@tonic-gate 	(void) memcpy(buffer, &buf[header_len], copy_cnt);
17960Sstevel@tonic-gate 	free(buf);
17970Sstevel@tonic-gate 
17980Sstevel@tonic-gate 	return (1);
17990Sstevel@tonic-gate }
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate int
mode_sense(int fd,uchar_t pc,int dbd,int page_len,uchar_t * buffer)18020Sstevel@tonic-gate mode_sense(int fd, uchar_t pc, int dbd, int page_len, uchar_t *buffer)
18030Sstevel@tonic-gate {
18040Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
18050Sstevel@tonic-gate 
18060Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
18070Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
18080Sstevel@tonic-gate 	scmd->uscsi_buflen = page_len;
18090Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buffer;
18100Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
18110Sstevel@tonic-gate 	scmd->uscsi_cdblen = 0xa;
18120Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = MODE_SENSE_10_CMD;
18130Sstevel@tonic-gate 	if (dbd) {
18140Sstevel@tonic-gate 		/* don't return any block descriptors */
18150Sstevel@tonic-gate 		scmd->uscsi_cdb[1] = 0x8;
18160Sstevel@tonic-gate 	}
18170Sstevel@tonic-gate 	/* the page code we want */
18180Sstevel@tonic-gate 	scmd->uscsi_cdb[2] = pc;
18190Sstevel@tonic-gate 	/* allocation length */
18200Sstevel@tonic-gate 	scmd->uscsi_cdb[7] = (page_len >> 8) & 0xff;
18210Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = page_len & 0xff;
18220Sstevel@tonic-gate 
18230Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
18240Sstevel@tonic-gate 		return (0);
18250Sstevel@tonic-gate 	return (1);
18260Sstevel@tonic-gate }
18270Sstevel@tonic-gate 
18280Sstevel@tonic-gate uint16_t
read_scsi16(void * addr)18290Sstevel@tonic-gate read_scsi16(void *addr)
18300Sstevel@tonic-gate {
18310Sstevel@tonic-gate 	uchar_t *ad = (uchar_t *)addr;
18320Sstevel@tonic-gate 	uint16_t ret;
18330Sstevel@tonic-gate 
18340Sstevel@tonic-gate 	ret = ((((uint16_t)ad[0]) << 8) | ad[1]);
18350Sstevel@tonic-gate 	return (ret);
18360Sstevel@tonic-gate }
18370Sstevel@tonic-gate 
18380Sstevel@tonic-gate /*
18390Sstevel@tonic-gate  * Allocate space for and return a pointer to a string
18400Sstevel@tonic-gate  * on the stack.  If the string is null, create
18410Sstevel@tonic-gate  * an empty string.
18420Sstevel@tonic-gate  * Use destroy_data() to free when no longer used.
18430Sstevel@tonic-gate  */
18440Sstevel@tonic-gate char *
alloc_string(s)18450Sstevel@tonic-gate alloc_string(s)
18460Sstevel@tonic-gate 	char    *s;
18470Sstevel@tonic-gate {
18480Sstevel@tonic-gate 	char    *ns;
18490Sstevel@tonic-gate 
18500Sstevel@tonic-gate 	if (s == (char *)NULL) {
18510Sstevel@tonic-gate 		ns = (char *)my_zalloc(1);
18520Sstevel@tonic-gate 	} else {
18530Sstevel@tonic-gate 		ns = (char *)my_zalloc(strlen(s) + 1);
18540Sstevel@tonic-gate 		(void) strcpy(ns, s);
18550Sstevel@tonic-gate 	}
18560Sstevel@tonic-gate 	return (ns);
18570Sstevel@tonic-gate }
18580Sstevel@tonic-gate 
18590Sstevel@tonic-gate /*
18600Sstevel@tonic-gate  * Follow symbolic links from the logical device name to
18610Sstevel@tonic-gate  * the /devfs physical device name.  To be complete, we
18620Sstevel@tonic-gate  * handle the case of multiple links.  This function
18630Sstevel@tonic-gate  * either returns NULL (no links, or some other error),
18640Sstevel@tonic-gate  * or the physical device name, alloc'ed on the heap.
18650Sstevel@tonic-gate  *
18660Sstevel@tonic-gate  * Note that the standard /devices prefix is stripped from
18670Sstevel@tonic-gate  * the final pathname, if present.  The trailing options
18680Sstevel@tonic-gate  * are also removed (":c, raw").
18690Sstevel@tonic-gate  */
18700Sstevel@tonic-gate static char *
get_physical_name(char * path)18710Sstevel@tonic-gate get_physical_name(char *path)
18720Sstevel@tonic-gate {
18730Sstevel@tonic-gate 	struct stat	stbuf;
18740Sstevel@tonic-gate 	int		i;
18750Sstevel@tonic-gate 	int		level;
18760Sstevel@tonic-gate 	char		*p;
18770Sstevel@tonic-gate 	char		s[MAXPATHLEN];
18780Sstevel@tonic-gate 	char		buf[MAXPATHLEN];
18790Sstevel@tonic-gate 	char		dir[MAXPATHLEN];
18800Sstevel@tonic-gate 	char		savedir[MAXPATHLEN];
18810Sstevel@tonic-gate 	char		*result = NULL;
18820Sstevel@tonic-gate 
18830Sstevel@tonic-gate 	if (getcwd(savedir, sizeof (savedir)) == NULL) {
18840Sstevel@tonic-gate 		DPRINTF1("getcwd() failed - %s\n", strerror(errno));
18850Sstevel@tonic-gate 		return (NULL);
18860Sstevel@tonic-gate 	}
18870Sstevel@tonic-gate 
18880Sstevel@tonic-gate 	(void) strcpy(s, path);
18890Sstevel@tonic-gate 	if ((p = strrchr(s, '/')) != NULL) {
18900Sstevel@tonic-gate 		*p = 0;
18910Sstevel@tonic-gate 	}
18920Sstevel@tonic-gate 	if (s[0] == 0) {
18930Sstevel@tonic-gate 		(void) strcpy(s, "/");
18940Sstevel@tonic-gate 	}
18950Sstevel@tonic-gate 	if (chdir(s) == -1) {
18960Sstevel@tonic-gate 		DPRINTF2("cannot chdir() to %s - %s\n",
1897*9525SPavel.Potoplyak@Sun.COM 		    s, strerror(errno));
18980Sstevel@tonic-gate 		goto exit;
18990Sstevel@tonic-gate 	}
19000Sstevel@tonic-gate 
19010Sstevel@tonic-gate 	level = 0;
19020Sstevel@tonic-gate 	(void) strcpy(s, path);
19030Sstevel@tonic-gate 	for (;;) {
19040Sstevel@tonic-gate 		/*
19050Sstevel@tonic-gate 		 * See if there's a real file out there.  If not,
19060Sstevel@tonic-gate 		 * we have a dangling link and we ignore it.
19070Sstevel@tonic-gate 		 */
19080Sstevel@tonic-gate 		if (stat(s, &stbuf) == -1) {
19090Sstevel@tonic-gate 			goto exit;
19100Sstevel@tonic-gate 		}
19110Sstevel@tonic-gate 		if (lstat(s, &stbuf) == -1) {
19120Sstevel@tonic-gate 			DPRINTF2("%s: lstat() failed - %s\n",
19130Sstevel@tonic-gate 			    s, strerror(errno));
19140Sstevel@tonic-gate 			goto exit;
19150Sstevel@tonic-gate 		}
19160Sstevel@tonic-gate 		/*
19170Sstevel@tonic-gate 		 * If the file is not a link, we're done one
19180Sstevel@tonic-gate 		 * way or the other.  If there were links,
19190Sstevel@tonic-gate 		 * return the full pathname of the resulting
19200Sstevel@tonic-gate 		 * file.
19210Sstevel@tonic-gate 		 */
19220Sstevel@tonic-gate 		if (!S_ISLNK(stbuf.st_mode)) {
19230Sstevel@tonic-gate 			if (level > 0) {
19240Sstevel@tonic-gate 				/*
19250Sstevel@tonic-gate 				 * Strip trailing options from the
19260Sstevel@tonic-gate 				 * physical device name
19270Sstevel@tonic-gate 				 */
19280Sstevel@tonic-gate 				if ((p = strrchr(s, ':')) != NULL) {
19290Sstevel@tonic-gate 					*p = 0;
19300Sstevel@tonic-gate 				}
19310Sstevel@tonic-gate 				/*
19320Sstevel@tonic-gate 				 * Get the current directory, and
19330Sstevel@tonic-gate 				 * glue the pieces together.
19340Sstevel@tonic-gate 				 */
19350Sstevel@tonic-gate 				if (getcwd(dir, sizeof (dir)) == NULL) {
19360Sstevel@tonic-gate 					DPRINTF1("getcwd() failed - %s\n",
1937*9525SPavel.Potoplyak@Sun.COM 					    strerror(errno));
19380Sstevel@tonic-gate 					goto exit;
19390Sstevel@tonic-gate 				}
19400Sstevel@tonic-gate 				(void) strcat(dir, "/");
19410Sstevel@tonic-gate 				(void) strcat(dir, s);
19420Sstevel@tonic-gate 				/*
19430Sstevel@tonic-gate 				 * If we have the standard fixed
19440Sstevel@tonic-gate 				 * /devices prefix, remove it.
19450Sstevel@tonic-gate 				 */
19460Sstevel@tonic-gate 				p = (strstr(dir, DEVFS_PREFIX) == dir) ?
1947*9525SPavel.Potoplyak@Sun.COM 				    dir+strlen(DEVFS_PREFIX) : dir;
19480Sstevel@tonic-gate 				result = alloc_string(p);
19490Sstevel@tonic-gate 			}
19500Sstevel@tonic-gate 			goto exit;
19510Sstevel@tonic-gate 		}
19520Sstevel@tonic-gate 		i = readlink(s, buf, sizeof (buf));
19530Sstevel@tonic-gate 		if (i == -1) {
19540Sstevel@tonic-gate 			DPRINTF2("%s: readlink() failed - %s\n",
1955*9525SPavel.Potoplyak@Sun.COM 			    s, strerror(errno));
19560Sstevel@tonic-gate 			goto exit;
19570Sstevel@tonic-gate 		}
19580Sstevel@tonic-gate 		level++;
19590Sstevel@tonic-gate 		buf[i] = 0;
19600Sstevel@tonic-gate 
19610Sstevel@tonic-gate 		/*
19620Sstevel@tonic-gate 		 * Break up the pathname into the directory
19630Sstevel@tonic-gate 		 * reference, if applicable and simple filename.
19640Sstevel@tonic-gate 		 * chdir()'ing to the directory allows us to
19650Sstevel@tonic-gate 		 * handle links with relative pathnames correctly.
19660Sstevel@tonic-gate 		 */
19670Sstevel@tonic-gate 		(void) strcpy(dir, buf);
19680Sstevel@tonic-gate 		if ((p = strrchr(dir, '/')) != NULL) {
19690Sstevel@tonic-gate 			*p = 0;
19700Sstevel@tonic-gate 			if (chdir(dir) == -1) {
19710Sstevel@tonic-gate 				DPRINTF2("cannot chdir() to %s - %s\n",
1972*9525SPavel.Potoplyak@Sun.COM 				    dir, strerror(errno));
19730Sstevel@tonic-gate 				goto exit;
19740Sstevel@tonic-gate 			}
19750Sstevel@tonic-gate 			(void) strcpy(s, p+1);
19760Sstevel@tonic-gate 		} else {
19770Sstevel@tonic-gate 			(void) strcpy(s, buf);
19780Sstevel@tonic-gate 		}
19790Sstevel@tonic-gate 	}
19800Sstevel@tonic-gate 
19810Sstevel@tonic-gate exit:
19820Sstevel@tonic-gate 	if (chdir(savedir) == -1) {
19830Sstevel@tonic-gate 		(void) printf("cannot chdir() to %s - %s\n",
19840Sstevel@tonic-gate 		    savedir, strerror(errno));
19850Sstevel@tonic-gate 	}
19860Sstevel@tonic-gate 
19870Sstevel@tonic-gate 	return (result);
19880Sstevel@tonic-gate }
19890Sstevel@tonic-gate 
19900Sstevel@tonic-gate static void
get_media_info(device_t * t_dev,char * sdev,char * pname,char * sn)19910Sstevel@tonic-gate get_media_info(device_t *t_dev, char *sdev, char *pname, char *sn)
19920Sstevel@tonic-gate {
19930Sstevel@tonic-gate 	struct dk_cinfo cinfo;
19947563SPrasad.Singamsetty@Sun.COM 	struct extvtoc vtocinfo;
19950Sstevel@tonic-gate 	float size;
19960Sstevel@tonic-gate 	int32_t fd;
19970Sstevel@tonic-gate 	smedia_handle_t handle;
19980Sstevel@tonic-gate 	struct dk_minfo mediainfo;
19990Sstevel@tonic-gate 	int device_type;
20000Sstevel@tonic-gate 
20010Sstevel@tonic-gate 	device_type = ioctl(t_dev->d_fd, DKIOCGMEDIAINFO, &mediainfo);
20020Sstevel@tonic-gate 
20030Sstevel@tonic-gate 	/*
20040Sstevel@tonic-gate 	 * Determine bus type.
20050Sstevel@tonic-gate 	 */
20060Sstevel@tonic-gate 	if (!ioctl(t_dev->d_fd, DKIOCINFO, &cinfo)) {
20070Sstevel@tonic-gate 		if (strstr(cinfo.dki_cname, "usb") || strstr(pname, "usb")) {
20080Sstevel@tonic-gate 			(void) printf("\tBus: USB\n");
20090Sstevel@tonic-gate 		} else if (strstr(cinfo.dki_cname, "firewire") ||
20100Sstevel@tonic-gate 		    strstr(pname, "firewire")) {
20110Sstevel@tonic-gate 			(void) printf("\tBus: Firewire\n");
20120Sstevel@tonic-gate 		} else if (strstr(cinfo.dki_cname, "ide") ||
20130Sstevel@tonic-gate 		    strstr(pname, "ide")) {
20140Sstevel@tonic-gate 			(void) printf("\tBus: IDE\n");
20150Sstevel@tonic-gate 		} else if (strstr(cinfo.dki_cname, "scsi") ||
20160Sstevel@tonic-gate 		    strstr(pname, "scsi")) {
20170Sstevel@tonic-gate 			(void) printf("\tBus: SCSI\n");
20180Sstevel@tonic-gate 		} else {
20190Sstevel@tonic-gate 			(void) printf("\tBus: <Unknown>\n");
20200Sstevel@tonic-gate 		}
20210Sstevel@tonic-gate 	} else {
20220Sstevel@tonic-gate 		(void) printf("\tBus: <Unknown>\n");
20230Sstevel@tonic-gate 	}
20240Sstevel@tonic-gate 
20250Sstevel@tonic-gate 	/*
20260Sstevel@tonic-gate 	 * Calculate size of media.
20270Sstevel@tonic-gate 	 */
20280Sstevel@tonic-gate 	if (!device_type &&
20290Sstevel@tonic-gate 	    (!ioctl(t_dev->d_fd, DKIOCGMEDIAINFO, &mediainfo))) {
20300Sstevel@tonic-gate 		size = (mediainfo.dki_lbsize*
20310Sstevel@tonic-gate 		    mediainfo.dki_capacity)/(1024.0*1024.0);
20320Sstevel@tonic-gate 		if (size < 1000) {
20330Sstevel@tonic-gate 			(void) printf("\tSize: %.1f MB\n", size);
20340Sstevel@tonic-gate 		} else {
20350Sstevel@tonic-gate 			size = size/1000;
20360Sstevel@tonic-gate 			(void) printf("\tSize: %.1f GB\n", size);
20370Sstevel@tonic-gate 		}
20380Sstevel@tonic-gate 	} else {
20390Sstevel@tonic-gate 		(void) printf("\tSize: <Unknown>\n");
20400Sstevel@tonic-gate 	}
20410Sstevel@tonic-gate 
20420Sstevel@tonic-gate 	/*
20430Sstevel@tonic-gate 	 * Print label.
20440Sstevel@tonic-gate 	 */
20457563SPrasad.Singamsetty@Sun.COM 	if (!device_type && (read_extvtoc(t_dev->d_fd,  &vtocinfo) >= 0)) {
20460Sstevel@tonic-gate 		if (*vtocinfo.v_volume) {
20470Sstevel@tonic-gate 			(void) printf("\tLabel: %s\n", vtocinfo.v_volume);
20480Sstevel@tonic-gate 		} else {
20490Sstevel@tonic-gate 			(void) printf("\tLabel: <None>\n");
20500Sstevel@tonic-gate 		}
20510Sstevel@tonic-gate 	} else {
20520Sstevel@tonic-gate 		(void) printf("\tLabel: <Unknown>\n");
20530Sstevel@tonic-gate 	}
20540Sstevel@tonic-gate 
20550Sstevel@tonic-gate 	/*
20560Sstevel@tonic-gate 	 * Acess permissions.
20570Sstevel@tonic-gate 	 */
20580Sstevel@tonic-gate 	if (device_type) {
20590Sstevel@tonic-gate 		(void) printf("\tAccess permissions: <Unknown>\n");
20600Sstevel@tonic-gate 		return;
20610Sstevel@tonic-gate 	}
20620Sstevel@tonic-gate 
2063*9525SPavel.Potoplyak@Sun.COM 	(void) fprintf(stdout, gettext("\tAccess permissions: "));
20640Sstevel@tonic-gate 	if (sn) {
20650Sstevel@tonic-gate 		/*
20660Sstevel@tonic-gate 		 * Set dev_name for process_p_flag().
20670Sstevel@tonic-gate 		 */
20680Sstevel@tonic-gate 		dev_name = sn;
20690Sstevel@tonic-gate 		fd = my_open(sn, O_RDONLY|O_NDELAY);
20700Sstevel@tonic-gate 	} else {
20710Sstevel@tonic-gate 		dev_name = sdev;
20720Sstevel@tonic-gate 		fd = my_open(sdev, O_RDONLY|O_NDELAY);
20730Sstevel@tonic-gate 	}
20740Sstevel@tonic-gate 	if (fd < 0)  {
20750Sstevel@tonic-gate 		(void) printf("<Unknown>\n");
20760Sstevel@tonic-gate 		DPRINTF("Could not open device.\n");
20770Sstevel@tonic-gate 		(void) close(fd);
20780Sstevel@tonic-gate 	} else {
20790Sstevel@tonic-gate 		/* register the fd with the libsmedia */
20800Sstevel@tonic-gate 		handle = smedia_get_handle(fd);
20810Sstevel@tonic-gate 		if (handle == NULL) {
20820Sstevel@tonic-gate 			(void) printf("<Unknown>\n");
20830Sstevel@tonic-gate 			DPRINTF("Failed to get libsmedia handle.\n");
20840Sstevel@tonic-gate 			(void) close(fd);
20850Sstevel@tonic-gate 		} else {
20860Sstevel@tonic-gate 			process_p_flag(handle, fd);
20870Sstevel@tonic-gate 		}
20880Sstevel@tonic-gate 	}
20891375Sphitran 	/* Clear dev_name */
20901375Sphitran 	dev_name = NULL;
20910Sstevel@tonic-gate }
2092