xref: /illumos-gate/usr/src/cmd/rmformat/rmf_misc.c (revision 75fafe14)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5e3397557Szk  * Common Development and Distribution License (the "License").
6e3397557Szk  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21342440ecSPrasad Singamsetty 
227c478bd9Sstevel@tonic-gate /*
23afb89a98SPavel Potoplyak  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * rmf_misc.c :
297c478bd9Sstevel@tonic-gate  *	Miscelleneous routines for rmformat.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <stdio.h>
347c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
357c478bd9Sstevel@tonic-gate #include <volmgt.h>
367c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
377c478bd9Sstevel@tonic-gate #include <sys/fdio.h>
387c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
397c478bd9Sstevel@tonic-gate #include <sys/termios.h>
407c478bd9Sstevel@tonic-gate #include <sys/mount.h>
417c478bd9Sstevel@tonic-gate #include <ctype.h>
427c478bd9Sstevel@tonic-gate #include <signal.h>
437c478bd9Sstevel@tonic-gate #include <sys/wait.h>
447c478bd9Sstevel@tonic-gate #include <dirent.h>
45bbed02dfSzk #include <priv_utils.h>
467c478bd9Sstevel@tonic-gate #include <stdarg.h>
477c478bd9Sstevel@tonic-gate #include "rmformat.h"
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate  * Definitions.
517c478bd9Sstevel@tonic-gate  */
527c478bd9Sstevel@tonic-gate #define	SENSE_KEY(rqbuf)	(rqbuf[2] & 0xf) /* scsi error category */
537c478bd9Sstevel@tonic-gate #define	ASC(rqbuf)		(rqbuf[12])	/* additional sense code */
547c478bd9Sstevel@tonic-gate #define	ASCQ(rqbuf)		(rqbuf[13])	/* ASC qualifier */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #define	DEFAULT_SCSI_TIMEOUT	60
577c478bd9Sstevel@tonic-gate #define	INQUIRY_CMD		0x12
587c478bd9Sstevel@tonic-gate #define	RQBUFLEN		32
597c478bd9Sstevel@tonic-gate #define	CD_RW			1		/* CD_RW/CD-R	*/
607c478bd9Sstevel@tonic-gate #define	WRITE_10_CMD		0x2A
617c478bd9Sstevel@tonic-gate #define	READ_INFO_CMD		0x51
627c478bd9Sstevel@tonic-gate #define	SYNC_CACHE_CMD		0x35
63*75fafe14SToomas Soome #define	CLOSE_TRACK_CMD		0x5B
647c478bd9Sstevel@tonic-gate #define	MODE_SENSE_10_CMD	0x5A
657c478bd9Sstevel@tonic-gate #define	DEVFS_PREFIX		"/devices"
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate int		uscsi_error;		 /* used for debugging failed uscsi */
687c478bd9Sstevel@tonic-gate char		rqbuf[RQBUFLEN];
697c478bd9Sstevel@tonic-gate static uint_t	total_retries;
707c478bd9Sstevel@tonic-gate static struct	uscsi_cmd uscmd;
717c478bd9Sstevel@tonic-gate static char	ucdb[16];
72*75fafe14SToomas Soome uchar_t		uscsi_status, rqstatus, rqresid;
737c478bd9Sstevel@tonic-gate int		total_devices_found = 0;
747c478bd9Sstevel@tonic-gate int		removable_found = 0;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate extern char	*global_intr_msg;
777c478bd9Sstevel@tonic-gate extern int	vol_running;
787c478bd9Sstevel@tonic-gate extern char	*dev_name;
797c478bd9Sstevel@tonic-gate extern int32_t	m_flag;
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * ON-private functions from libvolmgt
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate int	_dev_mounted(char *path);
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * Function prototypes.
887c478bd9Sstevel@tonic-gate  */
897c478bd9Sstevel@tonic-gate static int		my_umount(char *mountp);
907c478bd9Sstevel@tonic-gate static int		my_volrmmount(char *real_name);
917c478bd9Sstevel@tonic-gate static int		vol_name_to_dev_node(char *vname, char *found);
927c478bd9Sstevel@tonic-gate static int		vol_lookup(char *supplied, char *found);
937c478bd9Sstevel@tonic-gate static device_t		*get_device(char *user_supplied, char *node);
947c478bd9Sstevel@tonic-gate static char		*get_physical_name(char *path);
957c478bd9Sstevel@tonic-gate static int		lookup_device(char *supplied, char *found);
967c478bd9Sstevel@tonic-gate static void		fini_device(device_t *dev);
977c478bd9Sstevel@tonic-gate static int		is_cd(char *node);
987c478bd9Sstevel@tonic-gate void			*my_zalloc(size_t size);
997c478bd9Sstevel@tonic-gate void			err_msg(char *fmt, ...);
1007c478bd9Sstevel@tonic-gate int			inquiry(int fd, uchar_t *inq);
1017c478bd9Sstevel@tonic-gate struct uscsi_cmd	*get_uscsi_cmd(void);
1027c478bd9Sstevel@tonic-gate int			uscsi(int fd, struct uscsi_cmd *scmd);
1037c478bd9Sstevel@tonic-gate int			get_mode_page(int fd, int page_no, int pc, int buf_len,
1047c478bd9Sstevel@tonic-gate 			    uchar_t *buffer);
1057c478bd9Sstevel@tonic-gate int			mode_sense(int fd, uchar_t pc, int dbd, int page_len,
1067c478bd9Sstevel@tonic-gate 			    uchar_t *buffer);
1077c478bd9Sstevel@tonic-gate uint16_t		read_scsi16(void *addr);
1087c478bd9Sstevel@tonic-gate int			check_device(device_t *dev, int cond);
1097c478bd9Sstevel@tonic-gate static void		get_media_info(device_t *t_dev, char *sdev,
1107c478bd9Sstevel@tonic-gate 			    char *pname, char *sn);
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate extern void		process_p_flag(smedia_handle_t handle, int32_t fd);
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate void
my_perror(char * err_string)1157c478bd9Sstevel@tonic-gate my_perror(char *err_string)
1167c478bd9Sstevel@tonic-gate {
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	int error_no;
1197c478bd9Sstevel@tonic-gate 	if (errno == 0)
1207c478bd9Sstevel@tonic-gate 		return;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	error_no = errno;
1237c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s", err_string);
1247c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(" : "));
1257c478bd9Sstevel@tonic-gate 	errno = error_no;
1267c478bd9Sstevel@tonic-gate 	perror("");
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate int32_t
get_confirmation()1307c478bd9Sstevel@tonic-gate get_confirmation()
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	char c;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("Do you want to continue? (y/n)"));
1357c478bd9Sstevel@tonic-gate 	c = getchar();
1367c478bd9Sstevel@tonic-gate 	if (c == 'y' || c == 'Y')
1377c478bd9Sstevel@tonic-gate 		return (1);
1387c478bd9Sstevel@tonic-gate 	else if (c == 'n' || c == 'N')
1397c478bd9Sstevel@tonic-gate 		return (0);
1407c478bd9Sstevel@tonic-gate 	else {
1417c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Invalid choice\n"));
1427c478bd9Sstevel@tonic-gate 		return (0);
1437c478bd9Sstevel@tonic-gate 	}
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate void
get_passwd(struct smwp_state * wp,int32_t confirm)1487c478bd9Sstevel@tonic-gate get_passwd(struct smwp_state *wp, int32_t confirm)
1497c478bd9Sstevel@tonic-gate {
1507c478bd9Sstevel@tonic-gate 	char passwd[256], re_passwd[256];
1517c478bd9Sstevel@tonic-gate 	int32_t len;
1527c478bd9Sstevel@tonic-gate 	struct termios tio;
1537c478bd9Sstevel@tonic-gate 	int32_t echo_off = 0;
1547c478bd9Sstevel@tonic-gate 	FILE *in, *out;
1557c478bd9Sstevel@tonic-gate 	char *buf;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	in = fopen("/dev/tty", "r+");
1597c478bd9Sstevel@tonic-gate 	if (in == NULL) {
1607c478bd9Sstevel@tonic-gate 		in = stdin;
1617c478bd9Sstevel@tonic-gate 		out = stderr;
1627c478bd9Sstevel@tonic-gate 	} else {
1637c478bd9Sstevel@tonic-gate 		out = in;
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	/* Turn echoing off if it is on now.  */
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	if (tcgetattr(fileno(in), &tio) < 0) {
1697c478bd9Sstevel@tonic-gate 		PERROR("Echo off ioctl failed");
1707c478bd9Sstevel@tonic-gate 		exit(1);
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 	if (tio.c_lflag & ECHO) {
1737c478bd9Sstevel@tonic-gate 		tio.c_lflag &= ~ECHO;
1747c478bd9Sstevel@tonic-gate 		/* echo_off = tcsetattr(fileno(in), TCSAFLUSH, &tio) == 0; */
1757c478bd9Sstevel@tonic-gate 		echo_off = tcsetattr(fileno(in), TCSAFLUSH, &tio) == 0;
1767c478bd9Sstevel@tonic-gate 		tio.c_lflag |= ECHO;
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	/* CONSTCOND */
1807c478bd9Sstevel@tonic-gate 	while (1) {
1817c478bd9Sstevel@tonic-gate 		(void) fputs(
182afb89a98SPavel Potoplyak 		    gettext("Please enter password (32 chars maximum):"),
183afb89a98SPavel Potoplyak 		    out);
1847c478bd9Sstevel@tonic-gate 		(void) fflush(out);
1857c478bd9Sstevel@tonic-gate 		buf = fgets(passwd, (size_t)256, in);
1867c478bd9Sstevel@tonic-gate 		rewind(in);
1877c478bd9Sstevel@tonic-gate 		if (buf == NULL) {
1887c478bd9Sstevel@tonic-gate 			PERROR("Error reading password");
1897c478bd9Sstevel@tonic-gate 			continue;
1907c478bd9Sstevel@tonic-gate 		}
1917c478bd9Sstevel@tonic-gate 		len = strlen(passwd);
1927c478bd9Sstevel@tonic-gate 		(void) fputc('\n', out);
1937c478bd9Sstevel@tonic-gate 		len--;	/* To offset the \n */
1947c478bd9Sstevel@tonic-gate 		if ((len <= 0) || (len > 32)) {
1957c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
196afb89a98SPavel Potoplyak 			    gettext("Invalid length of password \n"));
1977c478bd9Sstevel@tonic-gate 			(void) fputs("Try again\n", out);
1987c478bd9Sstevel@tonic-gate 			continue;
1997c478bd9Sstevel@tonic-gate 		}
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 		if (!confirm)
2027c478bd9Sstevel@tonic-gate 			break;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 		(void) fputs("Please reenter password:", out);
2057c478bd9Sstevel@tonic-gate 		(void) fflush(out);
2067c478bd9Sstevel@tonic-gate 		buf = fgets(re_passwd, (size_t)256, in);
2077c478bd9Sstevel@tonic-gate 		rewind(in);
2087c478bd9Sstevel@tonic-gate 		(void) fputc('\n', out);
2097c478bd9Sstevel@tonic-gate 		if ((buf == NULL) || strcmp(passwd, re_passwd)) {
2107c478bd9Sstevel@tonic-gate 			(void) fputs("passwords did not match\n", out);
2117c478bd9Sstevel@tonic-gate 			(void) fputs("Try again\n", out);
2127c478bd9Sstevel@tonic-gate 		} else {
2137c478bd9Sstevel@tonic-gate 			break;
2147c478bd9Sstevel@tonic-gate 		}
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 	wp->sm_passwd_len = len;
2177c478bd9Sstevel@tonic-gate 	(void) strncpy(wp->sm_passwd, passwd, wp->sm_passwd_len);
2187c478bd9Sstevel@tonic-gate 	wp->sm_version = SMWP_STATE_V_1;
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	/* Restore echoing.  */
2217c478bd9Sstevel@tonic-gate 	if (echo_off)
2227c478bd9Sstevel@tonic-gate 		(void) tcsetattr(fileno(in), TCSAFLUSH, &tio);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate int32_t
check_and_unmount_vold(char * device_name,int32_t flag)2277c478bd9Sstevel@tonic-gate check_and_unmount_vold(char *device_name, int32_t flag)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate 	char *real_name;
2307c478bd9Sstevel@tonic-gate 	char *nm;
2317c478bd9Sstevel@tonic-gate 	char tmp_path_name[PATH_MAX];
2327c478bd9Sstevel@tonic-gate 	struct stat stat_buf;
2337c478bd9Sstevel@tonic-gate 	int32_t ret_val = 0;
2347c478bd9Sstevel@tonic-gate 	struct	mnttab	*mntp;
2357c478bd9Sstevel@tonic-gate 	FILE	*fp;
2367c478bd9Sstevel@tonic-gate 	int nl;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	DPRINTF1("Device name %s\n", device_name);
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	if (volmgt_running() == 0) {
2417c478bd9Sstevel@tonic-gate 		DPRINTF("Vold not running\n");
2427c478bd9Sstevel@tonic-gate 		return (0);
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 	if ((nm = volmgt_symname(device_name)) == NULL) {
2457c478bd9Sstevel@tonic-gate 		DPRINTF("path not managed\n");
2467c478bd9Sstevel@tonic-gate 		real_name = media_findname(device_name);
2477c478bd9Sstevel@tonic-gate 	} else {
2487c478bd9Sstevel@tonic-gate 		DPRINTF1("path managed as %s\n", nm);
2497c478bd9Sstevel@tonic-gate 		real_name = media_findname(nm);
2507c478bd9Sstevel@tonic-gate 		DPRINTF1("real name %s\n", real_name);
2517c478bd9Sstevel@tonic-gate 	}
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	if (real_name == NULL)
2547c478bd9Sstevel@tonic-gate 		return (-1);
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	/*
2577c478bd9Sstevel@tonic-gate 	 * To find out whether the device has been mounted by
2587c478bd9Sstevel@tonic-gate 	 * volume manager...
2597c478bd9Sstevel@tonic-gate 	 *
2607c478bd9Sstevel@tonic-gate 	 * Convert the real name to a block device address.
2617c478bd9Sstevel@tonic-gate 	 * Do a partial match with the mnttab entries.
2627c478bd9Sstevel@tonic-gate 	 * Make sure the match is in the beginning to avoid if
2637c478bd9Sstevel@tonic-gate 	 * anybody puts a label similiar to volume manager path names.
2647c478bd9Sstevel@tonic-gate 	 * Then use "volrmmount -e <dev_name>" if -U flag is set.
2657c478bd9Sstevel@tonic-gate 	 */
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	nl = strlen("/vol/dev/");
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	if (strncmp(real_name, "/vol/dev/", nl) != 0)
2707c478bd9Sstevel@tonic-gate 			return (0);
2717c478bd9Sstevel@tonic-gate 	if (real_name[nl] == 'r') {
2727c478bd9Sstevel@tonic-gate 		(void) snprintf(tmp_path_name, PATH_MAX, "%s%s", "/vol/dev/",
273afb89a98SPavel Potoplyak 		    &real_name[nl + 1]);
2747c478bd9Sstevel@tonic-gate 	} else {
2757c478bd9Sstevel@tonic-gate 		(void) snprintf(tmp_path_name, PATH_MAX, "%s", real_name);
2767c478bd9Sstevel@tonic-gate 	}
2777c478bd9Sstevel@tonic-gate 	DPRINTF1("%s \n", tmp_path_name);
2787c478bd9Sstevel@tonic-gate 	ret_val = stat(tmp_path_name, &stat_buf);
2797c478bd9Sstevel@tonic-gate 	if (ret_val < 0) {
2807c478bd9Sstevel@tonic-gate 		PERROR("Could not stat");
2817c478bd9Sstevel@tonic-gate 		return (-1);
2827c478bd9Sstevel@tonic-gate 	}
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 	fp = fopen("/etc/mnttab", "r");
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
2877c478bd9Sstevel@tonic-gate 		PERROR("Could not open /etc/mnttab");
2887c478bd9Sstevel@tonic-gate 		return (-1);
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	mntp = (struct mnttab *)malloc(sizeof (struct mnttab));
2927c478bd9Sstevel@tonic-gate 	if (mntp == NULL) {
2937c478bd9Sstevel@tonic-gate 		PERROR("malloc failed");
2947c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
2957c478bd9Sstevel@tonic-gate 		return (-1);
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 	errno = 0;
2987c478bd9Sstevel@tonic-gate 	while (getmntent(fp, mntp) == 0) {
2997c478bd9Sstevel@tonic-gate 		if (errno != 0) {
3007c478bd9Sstevel@tonic-gate 			PERROR("Error with mnttab");
3017c478bd9Sstevel@tonic-gate 			(void) fclose(fp);
3027c478bd9Sstevel@tonic-gate 			return (-1);
3037c478bd9Sstevel@tonic-gate 		}
3047c478bd9Sstevel@tonic-gate 		/* Is it a probable entry? */
3057c478bd9Sstevel@tonic-gate 		DPRINTF1(" %s \n", mntp->mnt_special);
3067c478bd9Sstevel@tonic-gate 		if (strstr(mntp->mnt_special, tmp_path_name) !=
307afb89a98SPavel Potoplyak 		    mntp->mnt_special) {
3087c478bd9Sstevel@tonic-gate 			/* Skip to next entry */
3097c478bd9Sstevel@tonic-gate 			continue;
3107c478bd9Sstevel@tonic-gate 		} else {
3117c478bd9Sstevel@tonic-gate 			DPRINTF1("Found!! %s\n", mntp->mnt_special);
3127c478bd9Sstevel@tonic-gate 			ret_val = 1;
3137c478bd9Sstevel@tonic-gate 			break;
3147c478bd9Sstevel@tonic-gate 		}
3157c478bd9Sstevel@tonic-gate 	}
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	if (ret_val == 1) {
3187c478bd9Sstevel@tonic-gate 		if (flag) {
3197c478bd9Sstevel@tonic-gate 			if (my_volrmmount(real_name) < 0) {
3207c478bd9Sstevel@tonic-gate 				ret_val = -1;
3217c478bd9Sstevel@tonic-gate 			}
3227c478bd9Sstevel@tonic-gate 		} else {
3237c478bd9Sstevel@tonic-gate 			ret_val = -1;
3247c478bd9Sstevel@tonic-gate 		}
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
3277c478bd9Sstevel@tonic-gate 	free(mntp);
3287c478bd9Sstevel@tonic-gate 	return (ret_val);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate  * This routine checks if a device has mounted partitions. The
3337c478bd9Sstevel@tonic-gate  * device name is assumed to be /dev/rdsk/cNtNdNsN. So, this can
3347c478bd9Sstevel@tonic-gate  * be used for SCSI and PCMCIA cards.
3357c478bd9Sstevel@tonic-gate  * Returns
3367c478bd9Sstevel@tonic-gate  *	 0 : if not mounted
3377c478bd9Sstevel@tonic-gate  *	 1 : if successfully unmounted
3387c478bd9Sstevel@tonic-gate  *	-1 : Any error or umount failed
3397c478bd9Sstevel@tonic-gate  */
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate int32_t
check_and_unmount_scsi(char * device_name,int32_t flag)3427c478bd9Sstevel@tonic-gate check_and_unmount_scsi(char *device_name, int32_t flag)
3437c478bd9Sstevel@tonic-gate {
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	struct	mnttab	*mntrefp;
3467c478bd9Sstevel@tonic-gate 	struct	mnttab	*mntp;
3477c478bd9Sstevel@tonic-gate 	FILE	*fp;
3487c478bd9Sstevel@tonic-gate 	char block_dev_name[PATH_MAX];
3497c478bd9Sstevel@tonic-gate 	char tmp_name[PATH_MAX];
3507c478bd9Sstevel@tonic-gate 	int32_t  i, j;
3517c478bd9Sstevel@tonic-gate 	int32_t unmounted = 0;
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	/*
3547c478bd9Sstevel@tonic-gate 	 * If the device name is not a character special, anyway we
3557c478bd9Sstevel@tonic-gate 	 * can not progress further
3567c478bd9Sstevel@tonic-gate 	 */
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	if (strncmp(device_name, "/dev/rdsk/c", strlen("/dev/rdsk/c")) != 0)
3597c478bd9Sstevel@tonic-gate 		return (0);
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	(void) snprintf(block_dev_name, PATH_MAX, "/dev/%s",
362afb89a98SPavel Potoplyak 	    &device_name[strlen("/dev/r")]);
3637c478bd9Sstevel@tonic-gate 	fp = fopen("/etc/mnttab", "r");
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
3667c478bd9Sstevel@tonic-gate 		PERROR("Could not open /etc/mnttab");
3677c478bd9Sstevel@tonic-gate 		return (-1);
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	mntrefp = (struct mnttab *)malloc(sizeof (struct mnttab));
3717c478bd9Sstevel@tonic-gate 	if (mntrefp == NULL) {
3727c478bd9Sstevel@tonic-gate 		PERROR("malloc failed");
3737c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
3747c478bd9Sstevel@tonic-gate 		return (-1);
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	mntp = (struct mnttab *)malloc(sizeof (struct mnttab));
3787c478bd9Sstevel@tonic-gate 	if (mntp == NULL) {
3797c478bd9Sstevel@tonic-gate 		PERROR("malloc failed");
3807c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
3817c478bd9Sstevel@tonic-gate 		free(mntrefp);
3827c478bd9Sstevel@tonic-gate 		return (-1);
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	/* Try all the partitions */
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	(void) snprintf(tmp_name, PATH_MAX, "/dev/%s",
3887c478bd9Sstevel@tonic-gate 	    &device_name[strlen("/dev/r")]);
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	tmp_name[strlen("/dev/dsk/c0t0d0s")] = '\0';
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	errno = 0;
3937c478bd9Sstevel@tonic-gate 	while (getmntent(fp, mntp) == 0) {
3947c478bd9Sstevel@tonic-gate 		if (errno != 0) {
3957c478bd9Sstevel@tonic-gate 			PERROR("Error with mnttab");
3967c478bd9Sstevel@tonic-gate 			(void) fclose(fp);
3977c478bd9Sstevel@tonic-gate 			return (-1);
3987c478bd9Sstevel@tonic-gate 		}
3997c478bd9Sstevel@tonic-gate 		/* Is it a probable entry? */
4007c478bd9Sstevel@tonic-gate 		if (strncmp(mntp->mnt_special, tmp_name, strlen(tmp_name))) {
4017c478bd9Sstevel@tonic-gate 			/* Skip to next entry */
4027c478bd9Sstevel@tonic-gate 			continue;
4037c478bd9Sstevel@tonic-gate 		}
4047c478bd9Sstevel@tonic-gate 		for (i = 0; i < NDKMAP; i++) {
4057c478bd9Sstevel@tonic-gate 			/* Check for ufs style mount devices */
4067c478bd9Sstevel@tonic-gate 			(void) snprintf(block_dev_name, PATH_MAX,
4077c478bd9Sstevel@tonic-gate 			    "%s%d", tmp_name, i);
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 			if (strcmp(mntp->mnt_special, block_dev_name) == 0) {
4107c478bd9Sstevel@tonic-gate 				if (flag) {
4117c478bd9Sstevel@tonic-gate 					if (my_umount(mntp->mnt_mountp) < 0) {
4127c478bd9Sstevel@tonic-gate 						(void) fclose(fp);
4137c478bd9Sstevel@tonic-gate 						return (-1);
4147c478bd9Sstevel@tonic-gate 					}
4157c478bd9Sstevel@tonic-gate 					unmounted = 1;
4167c478bd9Sstevel@tonic-gate 				} else {
4177c478bd9Sstevel@tonic-gate 					(void) fclose(fp);
4187c478bd9Sstevel@tonic-gate 					return (-1);
4197c478bd9Sstevel@tonic-gate 				}
4207c478bd9Sstevel@tonic-gate 				/* Skip to next entry */
4217c478bd9Sstevel@tonic-gate 				continue;
4227c478bd9Sstevel@tonic-gate 			}
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 			/* Try for :1 -> :24 for pcfs */
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 			for (j = 1; j < 24; j++) {
4277c478bd9Sstevel@tonic-gate 				(void) snprintf(block_dev_name, PATH_MAX,
4287c478bd9Sstevel@tonic-gate 				    "%s%d:%d", tmp_name, i, j);
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 				if (strcmp(mntp->mnt_special,
431afb89a98SPavel Potoplyak 				    block_dev_name) == 0) {
4327c478bd9Sstevel@tonic-gate 					if (flag) {
4337c478bd9Sstevel@tonic-gate 						if (my_umount(mntp->mnt_mountp)
434afb89a98SPavel Potoplyak 						    < 0) {
4357c478bd9Sstevel@tonic-gate 							(void) fclose(fp);
4367c478bd9Sstevel@tonic-gate 							return (-1);
4377c478bd9Sstevel@tonic-gate 						}
4387c478bd9Sstevel@tonic-gate 						unmounted = 1;
4397c478bd9Sstevel@tonic-gate 					} else {
4407c478bd9Sstevel@tonic-gate 						(void) fclose(fp);
4417c478bd9Sstevel@tonic-gate 						return (-1);
4427c478bd9Sstevel@tonic-gate 					}
4437c478bd9Sstevel@tonic-gate 					/* Skip to next entry */
4447c478bd9Sstevel@tonic-gate 					continue;
4457c478bd9Sstevel@tonic-gate 				}
4467c478bd9Sstevel@tonic-gate 				(void) snprintf(block_dev_name, PATH_MAX,
4477c478bd9Sstevel@tonic-gate 				    "%s%d:%c", tmp_name, i, 'b' + j);
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 				if (strcmp(mntp->mnt_special,
450afb89a98SPavel Potoplyak 				    block_dev_name) == 0) {
4517c478bd9Sstevel@tonic-gate 					if (flag) {
4527c478bd9Sstevel@tonic-gate 						if (my_umount(mntp->mnt_mountp)
453afb89a98SPavel Potoplyak 						    < 0) {
4547c478bd9Sstevel@tonic-gate 							(void) fclose(fp);
4557c478bd9Sstevel@tonic-gate 							return (-1);
4567c478bd9Sstevel@tonic-gate 						}
4577c478bd9Sstevel@tonic-gate 						unmounted = 1;
4587c478bd9Sstevel@tonic-gate 					} else {
4597c478bd9Sstevel@tonic-gate 						(void) fclose(fp);
4607c478bd9Sstevel@tonic-gate 						return (-1);
4617c478bd9Sstevel@tonic-gate 					}
4627c478bd9Sstevel@tonic-gate 					/* Skip to next entry */
4637c478bd9Sstevel@tonic-gate 					continue;
4647c478bd9Sstevel@tonic-gate 				}
4657c478bd9Sstevel@tonic-gate 			}
4667c478bd9Sstevel@tonic-gate 		}
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	if (unmounted)
4717c478bd9Sstevel@tonic-gate 		return (1);
4727c478bd9Sstevel@tonic-gate 	return (0);
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate /*
4767c478bd9Sstevel@tonic-gate  * This routine checks if a device has mounted partitions. The
4777c478bd9Sstevel@tonic-gate  * device name is assumed to be /dev/rdiskette. So, this can
4787c478bd9Sstevel@tonic-gate  * be used for Floppy controllers
4797c478bd9Sstevel@tonic-gate  * Returns
4807c478bd9Sstevel@tonic-gate  *	 0 : if not mounted
4817c478bd9Sstevel@tonic-gate  *	 1 : if successfully unmounted
4827c478bd9Sstevel@tonic-gate  *	-1 : Any error or unmount failed
4837c478bd9Sstevel@tonic-gate  */
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate int32_t
check_and_unmount_floppy(int32_t fd,int32_t flag)4867c478bd9Sstevel@tonic-gate check_and_unmount_floppy(int32_t fd, int32_t flag)
4877c478bd9Sstevel@tonic-gate {
4887c478bd9Sstevel@tonic-gate 	FILE	*fp = NULL;
4897c478bd9Sstevel@tonic-gate 	int32_t	mfd;
4907c478bd9Sstevel@tonic-gate 	struct dk_cinfo dkinfo, dkinfo_tmp;
4917c478bd9Sstevel@tonic-gate 	struct mnttab	mnt_record;
4927c478bd9Sstevel@tonic-gate 	struct mnttab	*mp = &mnt_record;
4937c478bd9Sstevel@tonic-gate 	struct stat	stbuf;
4947c478bd9Sstevel@tonic-gate 	char	raw_device[PATH_MAX];
4957c478bd9Sstevel@tonic-gate 	int32_t	found = 0;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &dkinfo) < 0) {
4997c478bd9Sstevel@tonic-gate 		return (-1);
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	if ((fp = fopen(MNTTAB, "r")) == NULL) {
5037c478bd9Sstevel@tonic-gate 		PERROR("Could not open /etc/mnttab");
5047c478bd9Sstevel@tonic-gate 		(void) close(fd);
5057c478bd9Sstevel@tonic-gate 		exit(3);
5067c478bd9Sstevel@tonic-gate 	}
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	while (getmntent(fp, mp) == 0) {
5097c478bd9Sstevel@tonic-gate 		if (strstr(mp->mnt_special, "/dev/fd") == NULL &&
5107c478bd9Sstevel@tonic-gate 		    strstr(mp->mnt_special, "/dev/disket") == NULL &&
5117c478bd9Sstevel@tonic-gate 		    strstr(mp->mnt_special, "/dev/c") == NULL) {
5127c478bd9Sstevel@tonic-gate 			continue;
5137c478bd9Sstevel@tonic-gate 		}
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 		(void) strcpy(raw_device, "/dev/r");
5167c478bd9Sstevel@tonic-gate 		(void) strcat(raw_device, mp->mnt_special + strlen("/dev/"));
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		/*
5207c478bd9Sstevel@tonic-gate 		 * Attempt to open the device.	If it fails, skip it.
5217c478bd9Sstevel@tonic-gate 		 */
5227c478bd9Sstevel@tonic-gate 
523e3397557Szk 		/* Turn on the privileges. */
524e3397557Szk 		(void) __priv_bracket(PRIV_ON);
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		mfd = open(raw_device, O_RDWR | O_NDELAY);
5277c478bd9Sstevel@tonic-gate 
528e3397557Szk 		/* Turn off the privileges. */
529e3397557Szk 		(void) __priv_bracket(PRIV_OFF);
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 		if (mfd < 0) {
5327c478bd9Sstevel@tonic-gate 			continue;
5337c478bd9Sstevel@tonic-gate 		}
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 		/*
5367c478bd9Sstevel@tonic-gate 		 * Must be a character device
5377c478bd9Sstevel@tonic-gate 		 */
5387c478bd9Sstevel@tonic-gate 		if (fstat(mfd, &stbuf) < 0 || !S_ISCHR(stbuf.st_mode)) {
5397c478bd9Sstevel@tonic-gate 			(void) close(mfd);
5407c478bd9Sstevel@tonic-gate 			continue;
5417c478bd9Sstevel@tonic-gate 		}
5427c478bd9Sstevel@tonic-gate 		/*
5437c478bd9Sstevel@tonic-gate 		 * Attempt to read the configuration info on the disk.
5447c478bd9Sstevel@tonic-gate 		 */
5457c478bd9Sstevel@tonic-gate 		if (ioctl(mfd, DKIOCINFO, &dkinfo_tmp) < 0) {
5467c478bd9Sstevel@tonic-gate 			(void) close(mfd);
5477c478bd9Sstevel@tonic-gate 			continue;
5487c478bd9Sstevel@tonic-gate 		}
5497c478bd9Sstevel@tonic-gate 		/*
5507c478bd9Sstevel@tonic-gate 		 * Finished with the opened device
5517c478bd9Sstevel@tonic-gate 		 */
5527c478bd9Sstevel@tonic-gate 		(void) close(mfd);
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 		/*
5557c478bd9Sstevel@tonic-gate 		 * If it's not the disk we're interested in, it doesn't apply.
5567c478bd9Sstevel@tonic-gate 		 */
5577c478bd9Sstevel@tonic-gate 		if (dkinfo.dki_ctype != dkinfo_tmp.dki_ctype ||
558afb89a98SPavel Potoplyak 		    dkinfo.dki_cnum != dkinfo_tmp.dki_cnum ||
559afb89a98SPavel Potoplyak 		    dkinfo.dki_unit != dkinfo_tmp.dki_unit) {
5607c478bd9Sstevel@tonic-gate 				continue;
5617c478bd9Sstevel@tonic-gate 		}
5627c478bd9Sstevel@tonic-gate 		/*
5637c478bd9Sstevel@tonic-gate 		 * It's a mount on the disk we're checking.  If we are
5647c478bd9Sstevel@tonic-gate 		 * checking whole disk, then we found trouble.	We can
5657c478bd9Sstevel@tonic-gate 		 * quit searching.
5667c478bd9Sstevel@tonic-gate 		 */
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 		if (flag) {
5697c478bd9Sstevel@tonic-gate 			if (my_umount(mp->mnt_mountp) < 0) {
5707c478bd9Sstevel@tonic-gate 				return (-1);
5717c478bd9Sstevel@tonic-gate 			}
5727c478bd9Sstevel@tonic-gate 			found = 1;
5737c478bd9Sstevel@tonic-gate 		} else {
5747c478bd9Sstevel@tonic-gate 			return (-1);
5757c478bd9Sstevel@tonic-gate 		}
5767c478bd9Sstevel@tonic-gate 	}
5777c478bd9Sstevel@tonic-gate 	return (found);
5787c478bd9Sstevel@tonic-gate }
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate int32_t
my_open(char * device_name,int32_t flags)5827c478bd9Sstevel@tonic-gate my_open(char *device_name, int32_t flags)
5837c478bd9Sstevel@tonic-gate {
5847c478bd9Sstevel@tonic-gate 	char *real_name;
5857c478bd9Sstevel@tonic-gate 	char *nm;
5867c478bd9Sstevel@tonic-gate 	char tmp_path_name[PATH_MAX];
5877c478bd9Sstevel@tonic-gate 	struct stat stat_buf;
5887c478bd9Sstevel@tonic-gate 	int32_t ret_val;
5897c478bd9Sstevel@tonic-gate 	int32_t fd;
5907c478bd9Sstevel@tonic-gate 	int32_t have_read_priv = 0;
5917c478bd9Sstevel@tonic-gate 	DIR *dirp;
5927c478bd9Sstevel@tonic-gate 	struct dirent *dp;
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	DPRINTF1("Device name %s\n", device_name);
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	if ((nm = volmgt_symname(device_name)) == NULL) {
5977c478bd9Sstevel@tonic-gate 		DPRINTF("path not managed\n");
5987c478bd9Sstevel@tonic-gate 		real_name = media_findname(device_name);
5997c478bd9Sstevel@tonic-gate 	} else {
6007c478bd9Sstevel@tonic-gate 		DPRINTF1("path managed as %s\n", nm);
6017c478bd9Sstevel@tonic-gate 		real_name = media_findname(nm);
6027c478bd9Sstevel@tonic-gate 		DPRINTF1("real name %s\n", real_name);
6037c478bd9Sstevel@tonic-gate 	}
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 	if (real_name == NULL)
6067c478bd9Sstevel@tonic-gate 		return (-1);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	(void) strcpy(tmp_path_name, real_name);
6097c478bd9Sstevel@tonic-gate 	ret_val = stat(tmp_path_name, &stat_buf);
6107c478bd9Sstevel@tonic-gate 	if (ret_val < 0) {
6117c478bd9Sstevel@tonic-gate 		PERROR("Could not stat");
6127c478bd9Sstevel@tonic-gate 		return (-1);
6137c478bd9Sstevel@tonic-gate 	}
6144bc0a2efScasper 	if (S_ISDIR(stat_buf.st_mode)) {
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 		/*
6177c478bd9Sstevel@tonic-gate 		 * Open the directory and look for the
6187c478bd9Sstevel@tonic-gate 		 * first non '.' entry.
6197c478bd9Sstevel@tonic-gate 		 * Since raw_read and raw_writes are used, we don't
6207c478bd9Sstevel@tonic-gate 		 * need to access the backup slice.
6217c478bd9Sstevel@tonic-gate 		 * For PCMCIA Memory cards, raw_read and raw_writes are
6227c478bd9Sstevel@tonic-gate 		 * not supported, but that is not a problem as, only slice2
6237c478bd9Sstevel@tonic-gate 		 * is allowed on PCMCIA memory cards.
6247c478bd9Sstevel@tonic-gate 		 */
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 		/*
6277c478bd9Sstevel@tonic-gate 		 * First make sure we are operating with a /vol/....
6287c478bd9Sstevel@tonic-gate 		 * Otherwise it can dangerous,
6297c478bd9Sstevel@tonic-gate 		 * e.g. rmformat -s /dev/rdsk
6307c478bd9Sstevel@tonic-gate 		 * We should not look into the directory contents here.
6317c478bd9Sstevel@tonic-gate 		 */
6327c478bd9Sstevel@tonic-gate 		if (strncmp(tmp_path_name, "/vol/dev/", strlen("/vol/dev/"))
633afb89a98SPavel Potoplyak 		    != 0) {
6347c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("The specified device \
6357c478bd9Sstevel@tonic-gate is not a raw device.\n"));
6367c478bd9Sstevel@tonic-gate 			exit(1);
6377c478bd9Sstevel@tonic-gate 		}
6387c478bd9Sstevel@tonic-gate 
639e3397557Szk 		/* Turn on the privileges. */
640e3397557Szk 		(void) __priv_bracket(PRIV_ON);
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 		dirp = opendir(tmp_path_name);
6437c478bd9Sstevel@tonic-gate 
644e3397557Szk 		/* Turn off the privileges. */
645e3397557Szk 		(void) __priv_bracket(PRIV_OFF);
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 		if (dirp == NULL) {
6487c478bd9Sstevel@tonic-gate 			return (-1);
6497c478bd9Sstevel@tonic-gate 		}
6507c478bd9Sstevel@tonic-gate 
651e3397557Szk 		/* Turn on the privileges. */
652e3397557Szk 		(void) __priv_bracket(PRIV_ON);
6537c478bd9Sstevel@tonic-gate 		have_read_priv = 1;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 		while ((dp = readdir(dirp)) != NULL) {
6567c478bd9Sstevel@tonic-gate 
657e3397557Szk 			/* Turn off the privileges. */
658e3397557Szk 			(void) __priv_bracket(PRIV_OFF);
6597c478bd9Sstevel@tonic-gate 			have_read_priv = 0;
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 			DPRINTF1("Found %s\n", dp->d_name);
6627c478bd9Sstevel@tonic-gate 			if ((strcmp(dp->d_name, ".") != 0) &&
6637c478bd9Sstevel@tonic-gate 			    (strcmp(dp->d_name, "..") != 0)) {
664*75fafe14SToomas Soome 				size_t len = strlen(tmp_path_name);
665*75fafe14SToomas Soome 
666*75fafe14SToomas Soome 				(void) snprintf(tmp_path_name + len,
667*75fafe14SToomas Soome 				    PATH_MAX - len, "/%s", dp->d_name);
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 				DPRINTF1("tmp_pathname is %s\n", tmp_path_name);
6707c478bd9Sstevel@tonic-gate 				break;
6717c478bd9Sstevel@tonic-gate 			}
6727c478bd9Sstevel@tonic-gate 
673e3397557Szk 			/* Turn on the privileges. */
674e3397557Szk 			(void) __priv_bracket(PRIV_ON);
6757c478bd9Sstevel@tonic-gate 			have_read_priv = 1;
6767c478bd9Sstevel@tonic-gate 		}
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 		if (have_read_priv) {
6797c478bd9Sstevel@tonic-gate 			/* drop the file_dac_read privilege */
680e3397557Szk 			(void) __priv_bracket(PRIV_OFF);
6817c478bd9Sstevel@tonic-gate 			have_read_priv = 0;
6827c478bd9Sstevel@tonic-gate 		}
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 		(void) closedir(dirp);
6857c478bd9Sstevel@tonic-gate 	}
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	if (volmgt_running() == 0) {
689e3397557Szk 		/* Turn on privileges. */
690e3397557Szk 		(void) __priv_bracket(PRIV_ON);
6917c478bd9Sstevel@tonic-gate 		have_read_priv = 1;
6927c478bd9Sstevel@tonic-gate 	}
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	fd = open(tmp_path_name, flags);
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	if (have_read_priv) {
697e3397557Szk 		/* Turn off privileges. */
698e3397557Szk 		(void) __priv_bracket(PRIV_OFF);
6997c478bd9Sstevel@tonic-gate 		have_read_priv = 0;
7007c478bd9Sstevel@tonic-gate 	}
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	DPRINTF1("path opened %s\n", tmp_path_name);
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	return (fd);
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate 
707342440ecSPrasad Singamsetty uint64_t
my_atoll(char * ptr)7087c478bd9Sstevel@tonic-gate my_atoll(char *ptr)
7097c478bd9Sstevel@tonic-gate {
7107c478bd9Sstevel@tonic-gate 	char *tmp_ptr = ptr;
7117c478bd9Sstevel@tonic-gate 	int32_t base = 10;
712342440ecSPrasad Singamsetty 	uint64_t ret_val;
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	while (*tmp_ptr) {
7157c478bd9Sstevel@tonic-gate 		if (isdigit(*tmp_ptr))
7167c478bd9Sstevel@tonic-gate 			tmp_ptr++;
7177c478bd9Sstevel@tonic-gate 		else {
7187c478bd9Sstevel@tonic-gate 			base = 16;
7197c478bd9Sstevel@tonic-gate 			break;
7207c478bd9Sstevel@tonic-gate 		}
7217c478bd9Sstevel@tonic-gate 	}
7227c478bd9Sstevel@tonic-gate 	tmp_ptr = ptr;
7237c478bd9Sstevel@tonic-gate 	if (base == 16) {
7247c478bd9Sstevel@tonic-gate 		if (strlen(tmp_ptr) < 3) {
7257c478bd9Sstevel@tonic-gate 			return (-1);
7267c478bd9Sstevel@tonic-gate 		}
7277c478bd9Sstevel@tonic-gate 		if (*tmp_ptr++ != '0' || (*tmp_ptr != 'x' && *tmp_ptr != 'X')) {
7287c478bd9Sstevel@tonic-gate 			return (-1);
7297c478bd9Sstevel@tonic-gate 		}
7307c478bd9Sstevel@tonic-gate 		tmp_ptr++;
7317c478bd9Sstevel@tonic-gate 		while (*tmp_ptr) {
7327c478bd9Sstevel@tonic-gate 			if (isxdigit(*tmp_ptr))
7337c478bd9Sstevel@tonic-gate 				tmp_ptr++;
7347c478bd9Sstevel@tonic-gate 			else {
7357c478bd9Sstevel@tonic-gate 				return (-1);
7367c478bd9Sstevel@tonic-gate 			}
7377c478bd9Sstevel@tonic-gate 		}
7387c478bd9Sstevel@tonic-gate 	}
739342440ecSPrasad Singamsetty 	ret_val = (uint64_t)strtoull(ptr, (char **)NULL, 0);
7407c478bd9Sstevel@tonic-gate 	return (ret_val);
7417c478bd9Sstevel@tonic-gate }
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate int32_t
write_sunos_label(int32_t fd,int32_t media_type)7447c478bd9Sstevel@tonic-gate write_sunos_label(int32_t fd, int32_t media_type)
7457c478bd9Sstevel@tonic-gate {
7467c478bd9Sstevel@tonic-gate 
747342440ecSPrasad Singamsetty 	struct extvtoc v_toc;
7487c478bd9Sstevel@tonic-gate 	int32_t ret;
7497c478bd9Sstevel@tonic-gate 
750342440ecSPrasad Singamsetty 	(void) memset(&v_toc, 0, sizeof (struct extvtoc));
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 	/* Initialize the vtoc information */
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	if (media_type == SM_FLOPPY) {
7557c478bd9Sstevel@tonic-gate 		struct fd_char fdchar;
7567c478bd9Sstevel@tonic-gate 		int32_t mult_factor;
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 		if (ioctl(fd, FDIOGCHAR, &fdchar) < 0) {
7597c478bd9Sstevel@tonic-gate 			PERROR("FDIOGCHAR failed");
7607c478bd9Sstevel@tonic-gate 			return (-1);
7617c478bd9Sstevel@tonic-gate 		}
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 		/* SPARC and x86 fd drivers use fdc_medium differently */
7647c478bd9Sstevel@tonic-gate #if defined(__sparc)
7657c478bd9Sstevel@tonic-gate 		mult_factor = (fdchar.fdc_medium) ? 2 : 1;
7667c478bd9Sstevel@tonic-gate #elif defined(__x86)
7677c478bd9Sstevel@tonic-gate 		mult_factor = (fdchar.fdc_medium == 5) ? 2 : 1;
7687c478bd9Sstevel@tonic-gate #else
7697c478bd9Sstevel@tonic-gate #error  No Platform defined
7707c478bd9Sstevel@tonic-gate #endif /* defined(__sparc) */
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 		/* initialize the vtoc structure */
7737c478bd9Sstevel@tonic-gate 		v_toc.v_nparts = 3;
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 		v_toc.v_part[0].p_start = 0;
7767c478bd9Sstevel@tonic-gate 		v_toc.v_part[0].p_size = (fdchar.fdc_ncyl - 1) * 2 *
777afb89a98SPavel Potoplyak 		    fdchar.fdc_secptrack * mult_factor;
7787c478bd9Sstevel@tonic-gate 		v_toc.v_part[1].p_start = (fdchar.fdc_ncyl - 1) * 2 *
779afb89a98SPavel Potoplyak 		    fdchar.fdc_secptrack * mult_factor;
7807c478bd9Sstevel@tonic-gate 		v_toc.v_part[1].p_size = 2 * fdchar.fdc_secptrack * mult_factor;
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 		v_toc.v_part[2].p_start = 0;
7837c478bd9Sstevel@tonic-gate 		v_toc.v_part[2].p_size = fdchar.fdc_ncyl * 2 *
784afb89a98SPavel Potoplyak 		    fdchar.fdc_secptrack * mult_factor;
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 	} else if (media_type == SM_SCSI_FLOPPY) {
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 		smedia_handle_t handle;
7897c478bd9Sstevel@tonic-gate 		smmedium_prop_t med_info;
7907c478bd9Sstevel@tonic-gate 		struct dk_geom dkgeom;
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 		/*
7947c478bd9Sstevel@tonic-gate 		 * call smedia_get_medium_property to get the
7957c478bd9Sstevel@tonic-gate 		 * correct media information, since DKIOCGMEDIAINFO
7967c478bd9Sstevel@tonic-gate 		 * may fail for unformatted media.
7977c478bd9Sstevel@tonic-gate 		 */
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 		handle = smedia_get_handle(fd);
8007c478bd9Sstevel@tonic-gate 		if (handle == NULL) {
8017c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
8027c478bd9Sstevel@tonic-gate 			gettext("Failed to get libsmedia handle.\n"));
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 			(void) close(fd);
8057c478bd9Sstevel@tonic-gate 			return (-1);
8067c478bd9Sstevel@tonic-gate 		}
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 		if (smedia_get_medium_property(handle, &med_info) < 0) {
8107c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
8117c478bd9Sstevel@tonic-gate 			    gettext("Get medium property failed \n"));
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 			(void) smedia_release_handle(handle);
8147c478bd9Sstevel@tonic-gate 			(void) close(fd);
8157c478bd9Sstevel@tonic-gate 			return (-1);
8167c478bd9Sstevel@tonic-gate 		}
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 		/* Fill in our own geometry information */
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 		dkgeom.dkg_pcyl = med_info.sm_pcyl;
8217c478bd9Sstevel@tonic-gate 		dkgeom.dkg_ncyl = med_info.sm_pcyl;
8227c478bd9Sstevel@tonic-gate 		dkgeom.dkg_nhead = med_info.sm_nhead;
8237c478bd9Sstevel@tonic-gate 		dkgeom.dkg_nsect = med_info.sm_nsect;
8247c478bd9Sstevel@tonic-gate 		dkgeom.dkg_acyl = 0;
8257c478bd9Sstevel@tonic-gate 		dkgeom.dkg_bcyl = 0;
8267c478bd9Sstevel@tonic-gate 		dkgeom.dkg_intrlv = 0;
8277c478bd9Sstevel@tonic-gate 		dkgeom.dkg_apc = 0;
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 		/*
8307c478bd9Sstevel@tonic-gate 		 * Try to set vtoc, if not successful we will
8317c478bd9Sstevel@tonic-gate 		 * continue to use the faked geometry information.
8327c478bd9Sstevel@tonic-gate 		 */
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 		(void) ioctl(fd, DKIOCSGEOM, &dkgeom);
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 		(void) smedia_release_handle(handle);
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 		/* we want the same partitioning as used for normal floppies */
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 		v_toc.v_part[0].p_start = 0;
841342440ecSPrasad Singamsetty 		v_toc.v_part[0].p_size =  (diskaddr_t)(dkgeom.dkg_ncyl - 1) *
8427c478bd9Sstevel@tonic-gate 		    dkgeom.dkg_nhead * dkgeom.dkg_nsect;
8437c478bd9Sstevel@tonic-gate 
844342440ecSPrasad Singamsetty 		v_toc.v_part[1].p_start = (diskaddr_t)(dkgeom.dkg_ncyl - 1) *
8457c478bd9Sstevel@tonic-gate 		    dkgeom.dkg_nhead * dkgeom.dkg_nsect;
8467c478bd9Sstevel@tonic-gate 		v_toc.v_part[1].p_size =  dkgeom.dkg_nhead * dkgeom.dkg_nsect;
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 		v_toc.v_part[2].p_start = 0;
849342440ecSPrasad Singamsetty 		v_toc.v_part[2].p_size = (diskaddr_t)dkgeom.dkg_ncyl *
8507c478bd9Sstevel@tonic-gate 		    dkgeom.dkg_nhead * dkgeom.dkg_nsect;
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 		/* both write_vtoc and DKIOCSVTOC require V_NUMPAR partitions */
8537c478bd9Sstevel@tonic-gate 		v_toc.v_nparts = V_NUMPAR;
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 	} else {
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 		return (0);
8587c478bd9Sstevel@tonic-gate 	}
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 	v_toc.v_sanity = VTOC_SANE;
8617c478bd9Sstevel@tonic-gate 	v_toc.v_version = V_VERSION;
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 	/*
8647c478bd9Sstevel@tonic-gate 	 * The label structure is set up for DEV_BSIZE(512 byte) blocks,
8657c478bd9Sstevel@tonic-gate 	 * even though a medium density diskette has 1024 byte blocks
8667c478bd9Sstevel@tonic-gate 	 * See dklabel.h for more details.
8677c478bd9Sstevel@tonic-gate 	 */
8687c478bd9Sstevel@tonic-gate 	v_toc.v_sectorsz = DEV_BSIZE;
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	/* let the fd driver finish constructing the label and writing it. */
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 
873e3397557Szk 	/* Turn on the privileges. */
874e3397557Szk 	(void) __priv_bracket(PRIV_ON);
8757c478bd9Sstevel@tonic-gate 
876342440ecSPrasad Singamsetty 	ret = write_extvtoc(fd, &v_toc);
8777c478bd9Sstevel@tonic-gate 
878e3397557Szk 	/* Turn off the privileges. */
879e3397557Szk 	(void) __priv_bracket(PRIV_OFF);
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 	if (ret < 0) {
8827c478bd9Sstevel@tonic-gate 		PERROR("Write vtoc");
8837c478bd9Sstevel@tonic-gate 		DPRINTF1("Write vtoc failed errno:%d\n", errno);
8847c478bd9Sstevel@tonic-gate 		return (-1);
8857c478bd9Sstevel@tonic-gate 	}
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	return (0);
8887c478bd9Sstevel@tonic-gate }
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate static void
intr_sig_handler()8917c478bd9Sstevel@tonic-gate intr_sig_handler()
8927c478bd9Sstevel@tonic-gate {
8937c478bd9Sstevel@tonic-gate 	char c;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(global_intr_msg));
8967c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
8977c478bd9Sstevel@tonic-gate 	    gettext("\nDo you want to stop formatting?(y/n)"));
8987c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
8997c478bd9Sstevel@tonic-gate 	rewind(stdin);
900afb89a98SPavel Potoplyak 	while ((c = getchar()) == -1)
901afb89a98SPavel Potoplyak 		;
9027c478bd9Sstevel@tonic-gate 	if (c == 'y' || c == 'Y') {
9037c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Format interrupted\n"));
9047c478bd9Sstevel@tonic-gate 		exit(1);
9057c478bd9Sstevel@tonic-gate 	} else if (c == 'n' || c == 'N')
9067c478bd9Sstevel@tonic-gate 		return;
9077c478bd9Sstevel@tonic-gate 	else {
9087c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Did not interrupt\n"));
9097c478bd9Sstevel@tonic-gate 		return;
9107c478bd9Sstevel@tonic-gate 	}
9117c478bd9Sstevel@tonic-gate }
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate static struct sigaction act, oact;
9147c478bd9Sstevel@tonic-gate void
trap_SIGINT(void)915*75fafe14SToomas Soome trap_SIGINT(void)
9167c478bd9Sstevel@tonic-gate {
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 	act.sa_handler = intr_sig_handler;
9197c478bd9Sstevel@tonic-gate 	(void) memset(&act.sa_mask, 0, sizeof (sigset_t));
9207c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_RESTART; /* | SA_NODEFER; */
9217c478bd9Sstevel@tonic-gate 	if (sigaction(SIGINT, &act, &oact) < 0) {
9227c478bd9Sstevel@tonic-gate 		DPRINTF("sigset failed\n");
9237c478bd9Sstevel@tonic-gate 		return;
9247c478bd9Sstevel@tonic-gate 	}
9257c478bd9Sstevel@tonic-gate }
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate void
release_SIGINT(void)928*75fafe14SToomas Soome release_SIGINT(void)
9297c478bd9Sstevel@tonic-gate {
9307c478bd9Sstevel@tonic-gate 	if (sigaction(SIGINT, &oact, (struct sigaction *)NULL) < 0) {
9317c478bd9Sstevel@tonic-gate 		DPRINTF("sigunset failed\n");
9327c478bd9Sstevel@tonic-gate 		return;
9337c478bd9Sstevel@tonic-gate 	}
9347c478bd9Sstevel@tonic-gate }
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@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)937342440ecSPrasad Singamsetty verify(smedia_handle_t handle, int32_t fd, diskaddr_t start_sector,
938*75fafe14SToomas Soome     uint32_t nblocks, char *buf,
939*75fafe14SToomas Soome     int32_t flag, int32_t blocksize, int32_t no_raw_rw)
9407c478bd9Sstevel@tonic-gate {
941342440ecSPrasad Singamsetty 	uint64_t ret;
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate 	DPRINTF("ANALYSE MEDIA \n");
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 	if ((flag == VERIFY_READ) && (!no_raw_rw)) {
9477c478bd9Sstevel@tonic-gate 
948e3397557Szk 		/* Turn on the privileges. */
949e3397557Szk 		(void) __priv_bracket(PRIV_ON);
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 		ret = smedia_raw_read(handle, start_sector, buf, nblocks *
952afb89a98SPavel Potoplyak 		    blocksize);
9537c478bd9Sstevel@tonic-gate 
954e3397557Szk 		/* Turn off the privileges. */
955e3397557Szk 		(void) __priv_bracket(PRIV_OFF);
9567c478bd9Sstevel@tonic-gate 
957342440ecSPrasad Singamsetty 		if (ret != (nblocks * blocksize))
958342440ecSPrasad Singamsetty 			return (-1);
9597c478bd9Sstevel@tonic-gate 		return (0);
9607c478bd9Sstevel@tonic-gate 
961342440ecSPrasad Singamsetty 	} else if ((flag == VERIFY_WRITE) && (!no_raw_rw)) {
9627c478bd9Sstevel@tonic-gate 
963e3397557Szk 		/* Turn on privileges. */
964e3397557Szk 		(void) __priv_bracket(PRIV_ON);
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 		ret = smedia_raw_write(handle, start_sector, buf, nblocks *
967afb89a98SPavel Potoplyak 		    blocksize);
9687c478bd9Sstevel@tonic-gate 
969e3397557Szk 		/* Turn off the privileges. */
970e3397557Szk 		(void) __priv_bracket(PRIV_OFF);
9717c478bd9Sstevel@tonic-gate 
972342440ecSPrasad Singamsetty 		if (ret != (blocksize * nblocks))
9737c478bd9Sstevel@tonic-gate 			return (-1);
9747c478bd9Sstevel@tonic-gate 		return (0);
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 	} else if ((flag == VERIFY_READ) && (no_raw_rw)) {
9777c478bd9Sstevel@tonic-gate 		ret = llseek(fd, start_sector * blocksize, SEEK_SET);
9787c478bd9Sstevel@tonic-gate 		if (ret != start_sector * blocksize) {
9797c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Seek failed\n"));
9807c478bd9Sstevel@tonic-gate 			return (-2);
9817c478bd9Sstevel@tonic-gate 		}
9827c478bd9Sstevel@tonic-gate 
983e3397557Szk 		/* Turn on the privileges. */
984e3397557Szk 		(void) __priv_bracket(PRIV_ON);
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 		ret = read(fd, buf, nblocks * blocksize);
9877c478bd9Sstevel@tonic-gate 
988e3397557Szk 		/* Turn off the privileges. */
989e3397557Szk 		(void) __priv_bracket(PRIV_OFF);
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 		if (ret != nblocks * blocksize) {
9927c478bd9Sstevel@tonic-gate 			return (-1);
9937c478bd9Sstevel@tonic-gate 		}
9947c478bd9Sstevel@tonic-gate 		return (0);
9957c478bd9Sstevel@tonic-gate 	} else if ((flag == VERIFY_WRITE) && (no_raw_rw)) {
9967c478bd9Sstevel@tonic-gate 		ret = llseek(fd, start_sector * blocksize, SEEK_SET);
9977c478bd9Sstevel@tonic-gate 		if (ret != start_sector * blocksize) {
9987c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Seek failed\n"));
9997c478bd9Sstevel@tonic-gate 			return (-2);
10007c478bd9Sstevel@tonic-gate 		}
10017c478bd9Sstevel@tonic-gate 
1002e3397557Szk 		/* Turn on the privileges. */
1003e3397557Szk 		(void) __priv_bracket(PRIV_ON);
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 		ret = write(fd, buf, nblocks * blocksize);
10067c478bd9Sstevel@tonic-gate 
1007e3397557Szk 		/* Turn off the privileges. */
1008e3397557Szk 		(void) __priv_bracket(PRIV_OFF);
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 		if (ret != nblocks * blocksize) {
10117c478bd9Sstevel@tonic-gate 			return (-1);
10127c478bd9Sstevel@tonic-gate 		}
10137c478bd9Sstevel@tonic-gate 		return (0);
10147c478bd9Sstevel@tonic-gate 	} else {
10157c478bd9Sstevel@tonic-gate 		DPRINTF("Illegal parameter to verify_analysis!\n");
10167c478bd9Sstevel@tonic-gate 		return (-1);
10177c478bd9Sstevel@tonic-gate 	}
10187c478bd9Sstevel@tonic-gate }
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate static int
my_umount(char * mountp)10217c478bd9Sstevel@tonic-gate my_umount(char *mountp)
10227c478bd9Sstevel@tonic-gate {
10237c478bd9Sstevel@tonic-gate 	pid_t	pid;	/* forked proc's pid */
10247c478bd9Sstevel@tonic-gate 	int	rval;	/* proc's return value */
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 	/* create a child to unmount the path */
10287c478bd9Sstevel@tonic-gate 
1029e3397557Szk 	/* Turn on the privileges */
1030e3397557Szk 	(void) __priv_bracket(PRIV_ON);
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	pid = fork();
10337c478bd9Sstevel@tonic-gate 
1034e3397557Szk 	/* Turn off the privileges. */
1035e3397557Szk 	(void) __priv_bracket(PRIV_OFF);
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	if (pid < 0) {
10387c478bd9Sstevel@tonic-gate 		PERROR("fork failed");
10397c478bd9Sstevel@tonic-gate 		exit(0);
10407c478bd9Sstevel@tonic-gate 	}
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	if (pid == 0) {
10437c478bd9Sstevel@tonic-gate 		/* the child */
10447c478bd9Sstevel@tonic-gate 		/* get rid of those nasty err messages */
10457c478bd9Sstevel@tonic-gate 		DPRINTF1("call_unmount_prog: calling %s \n", mountp);
10467c478bd9Sstevel@tonic-gate 
1047e3397557Szk 		/* Turn on the priviliges. */
1048e3397557Szk 		(void) __priv_bracket(PRIV_ON);
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 		if (execl("/usr/sbin/umount", "/usr/sbin/umount", mountp,
1051afb89a98SPavel Potoplyak 		    NULL) < 0) {
10527c478bd9Sstevel@tonic-gate 			perror("exec failed");
1053e3397557Szk 			/* Turn off the privileges */
1054e3397557Szk 			(void) __priv_bracket(PRIV_OFF);
10557c478bd9Sstevel@tonic-gate 			exit(-1);
10567c478bd9Sstevel@tonic-gate 		}
10577c478bd9Sstevel@tonic-gate 	}
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 	/* wait for the umount command to exit */
10607c478bd9Sstevel@tonic-gate 	rval = 0;
10617c478bd9Sstevel@tonic-gate 	if (waitpid(pid, &rval, 0) == pid) {
10627c478bd9Sstevel@tonic-gate 		if (WIFEXITED(rval)) {
10637c478bd9Sstevel@tonic-gate 			if (WEXITSTATUS(rval) == 0) {
10647c478bd9Sstevel@tonic-gate 				DPRINTF("umount : Success\n");
10657c478bd9Sstevel@tonic-gate 				return (1);
10667c478bd9Sstevel@tonic-gate 			}
10677c478bd9Sstevel@tonic-gate 		}
10687c478bd9Sstevel@tonic-gate 	}
10697c478bd9Sstevel@tonic-gate 	return (-1);
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate static int
my_volrmmount(char * real_name)10737c478bd9Sstevel@tonic-gate my_volrmmount(char *real_name)
10747c478bd9Sstevel@tonic-gate {
10757c478bd9Sstevel@tonic-gate 	int pid, rval;
10767c478bd9Sstevel@tonic-gate 
1077e3397557Szk 	/* Turn on the privileges. */
1078e3397557Szk 	(void) __priv_bracket(PRIV_ON);
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 	pid = fork();
10817c478bd9Sstevel@tonic-gate 
1082e3397557Szk 	/* Turn off the privileges. */
1083e3397557Szk 	(void) __priv_bracket(PRIV_OFF);
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate 	/* create a child to unmount the path */
10867c478bd9Sstevel@tonic-gate 	if (pid < 0) {
10877c478bd9Sstevel@tonic-gate 		PERROR("fork failed");
10887c478bd9Sstevel@tonic-gate 		exit(0);
10897c478bd9Sstevel@tonic-gate 	}
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 	if (pid == 0) {
10927c478bd9Sstevel@tonic-gate 		/* the child */
10937c478bd9Sstevel@tonic-gate 		/* get rid of those nasty err messages */
10947c478bd9Sstevel@tonic-gate 		DPRINTF1("call_unmount_prog: calling %s \n",
1095afb89a98SPavel Potoplyak 		    "/usr/bin/volrmmount");
10967c478bd9Sstevel@tonic-gate 
1097e3397557Szk 		/* Turn on the privileges. */
1098e3397557Szk 		(void) __priv_bracket(PRIV_ON);
10997c478bd9Sstevel@tonic-gate 		if (execl("/usr/bin/volrmmount", "/usr/bin/volrmmount", "-e",
1100afb89a98SPavel Potoplyak 		    real_name, NULL) < 0) {
11017c478bd9Sstevel@tonic-gate 			PERROR("volrmmount exec failed");
1102e3397557Szk 			/* Turn off the privileges */
1103e3397557Szk 			(void) __priv_bracket(PRIV_OFF);
11047c478bd9Sstevel@tonic-gate 			exit(-1);
11057c478bd9Sstevel@tonic-gate 		}
11067c478bd9Sstevel@tonic-gate 	} else if (waitpid(pid, &rval, 0) == pid) {
11077c478bd9Sstevel@tonic-gate 		if (WIFEXITED(rval)) {
11087c478bd9Sstevel@tonic-gate 			if (WEXITSTATUS(rval) == 0) {
11097c478bd9Sstevel@tonic-gate 				DPRINTF("volrmmount: Success\n");
11107c478bd9Sstevel@tonic-gate 				return (1);
11117c478bd9Sstevel@tonic-gate 			}
11127c478bd9Sstevel@tonic-gate 		}
11137c478bd9Sstevel@tonic-gate 	}
11147c478bd9Sstevel@tonic-gate 	return (-1);
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate int
find_device(int defer,char * tmpstr)11187c478bd9Sstevel@tonic-gate find_device(int defer, char *tmpstr)
11197c478bd9Sstevel@tonic-gate {
11207c478bd9Sstevel@tonic-gate 	DIR *dir;
11217c478bd9Sstevel@tonic-gate 	struct dirent *dirent;
11227c478bd9Sstevel@tonic-gate 	char sdev[PATH_MAX], dev[PATH_MAX], *pname;
11237c478bd9Sstevel@tonic-gate 	device_t *t_dev;
1124dd97b1d6Sphitran 	int removable = 0;
1125dd97b1d6Sphitran 	int device_type = 0;
1126dd97b1d6Sphitran 	int hotpluggable = 0;
11277c478bd9Sstevel@tonic-gate 	struct dk_minfo mediainfo;
11287c478bd9Sstevel@tonic-gate 	static int found = 0;
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 	dir = opendir("/dev/rdsk");
11317c478bd9Sstevel@tonic-gate 	if (dir == NULL)
11327c478bd9Sstevel@tonic-gate 		return (-1);
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 	total_devices_found = 0;
11357c478bd9Sstevel@tonic-gate 	while ((dirent = readdir(dir)) != NULL) {
11367c478bd9Sstevel@tonic-gate 		if (dirent->d_name[0] == '.') {
11377c478bd9Sstevel@tonic-gate 			continue;
11387c478bd9Sstevel@tonic-gate 		}
11397c478bd9Sstevel@tonic-gate 		(void) snprintf(sdev, PATH_MAX, "/dev/rdsk/%s",
11407c478bd9Sstevel@tonic-gate 		    dirent->d_name);
11417c478bd9Sstevel@tonic-gate #ifdef sparc
11427c478bd9Sstevel@tonic-gate 		if (!strstr(sdev, "s2")) {
11437c478bd9Sstevel@tonic-gate 			continue;
11447c478bd9Sstevel@tonic-gate 		}
11457c478bd9Sstevel@tonic-gate #else /* x86 */
11467c478bd9Sstevel@tonic-gate 		if (vol_running) {
11477c478bd9Sstevel@tonic-gate 			if (!(strstr(sdev, "s2") || strstr(sdev, "p0"))) {
11487c478bd9Sstevel@tonic-gate 				continue;
11497c478bd9Sstevel@tonic-gate 			}
11507c478bd9Sstevel@tonic-gate 		} else {
11517c478bd9Sstevel@tonic-gate 			if (!strstr(sdev, "p0")) {
11527c478bd9Sstevel@tonic-gate 				continue;
11537c478bd9Sstevel@tonic-gate 			}
11547c478bd9Sstevel@tonic-gate 		}
11557c478bd9Sstevel@tonic-gate #endif
11567c478bd9Sstevel@tonic-gate 		if (!lookup_device(sdev, dev)) {
11577c478bd9Sstevel@tonic-gate 			continue;
11587c478bd9Sstevel@tonic-gate 		}
11597c478bd9Sstevel@tonic-gate 		if ((t_dev = get_device(NULL, dev)) == NULL) {
11607c478bd9Sstevel@tonic-gate 			continue;
11617c478bd9Sstevel@tonic-gate 		}
11627c478bd9Sstevel@tonic-gate 		total_devices_found++;
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 		if ((!defer) && !found) {
11657c478bd9Sstevel@tonic-gate 			char *sn, *tmpbuf;
11667c478bd9Sstevel@tonic-gate 			/*
11677c478bd9Sstevel@tonic-gate 			 * dev_name is an optional command line input.
11687c478bd9Sstevel@tonic-gate 			 */
11697c478bd9Sstevel@tonic-gate 			if (dev_name) {
11707c478bd9Sstevel@tonic-gate 				if (strstr(dirent->d_name, tmpstr)) {
11717c478bd9Sstevel@tonic-gate 					found = 1;
11727c478bd9Sstevel@tonic-gate 				} else if (!vol_running) {
11737c478bd9Sstevel@tonic-gate 					continue;
11747c478bd9Sstevel@tonic-gate 				}
11757c478bd9Sstevel@tonic-gate 			}
11767c478bd9Sstevel@tonic-gate 			/*
11777c478bd9Sstevel@tonic-gate 			 * volmgt_symname() returns NULL if the device
11787c478bd9Sstevel@tonic-gate 			 * is not managed by volmgt.
11797c478bd9Sstevel@tonic-gate 			 */
11807c478bd9Sstevel@tonic-gate 			sn = volmgt_symname(sdev);
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 			if (vol_running && (sn != NULL)) {
11837c478bd9Sstevel@tonic-gate 				if (strstr(sn, "dev") == NULL) {
11847c478bd9Sstevel@tonic-gate 					tmpbuf = (char *)my_zalloc(PATH_MAX);
11857c478bd9Sstevel@tonic-gate 					(void) strcpy(tmpbuf,
11867c478bd9Sstevel@tonic-gate 					    "/vol/dev/aliases/");
11877c478bd9Sstevel@tonic-gate 					(void) strcat(tmpbuf, sn);
11887c478bd9Sstevel@tonic-gate 					free(sn);
11897c478bd9Sstevel@tonic-gate 					sn = tmpbuf;
11907c478bd9Sstevel@tonic-gate 				}
11917c478bd9Sstevel@tonic-gate 				if (dev_name && !found) {
11927c478bd9Sstevel@tonic-gate 					if (!strstr(tmpbuf, tmpstr)) {
11937c478bd9Sstevel@tonic-gate 						continue;
11947c478bd9Sstevel@tonic-gate 					} else {
11957c478bd9Sstevel@tonic-gate 						found = 1;
11967c478bd9Sstevel@tonic-gate 					}
11977c478bd9Sstevel@tonic-gate 				}
11987c478bd9Sstevel@tonic-gate 			}
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 			/*
12017c478bd9Sstevel@tonic-gate 			 * Get device type information for CD/DVD devices.
12027c478bd9Sstevel@tonic-gate 			 */
12037c478bd9Sstevel@tonic-gate 			if (is_cd(dev)) {
12047c478bd9Sstevel@tonic-gate 				if (check_device(t_dev,
12057c478bd9Sstevel@tonic-gate 				    CHECK_DEVICE_IS_DVD_WRITABLE)) {
12067c478bd9Sstevel@tonic-gate 					device_type = DK_DVDR;
12077c478bd9Sstevel@tonic-gate 				} else if (check_device(t_dev,
12087c478bd9Sstevel@tonic-gate 				    CHECK_DEVICE_IS_DVD_READABLE)) {
12097c478bd9Sstevel@tonic-gate 					device_type = DK_DVDROM;
12107c478bd9Sstevel@tonic-gate 				} else if (check_device(t_dev,
12117c478bd9Sstevel@tonic-gate 				    CHECK_DEVICE_IS_CD_WRITABLE)) {
12127c478bd9Sstevel@tonic-gate 					device_type = DK_CDR;
12137c478bd9Sstevel@tonic-gate 				} else {
12147c478bd9Sstevel@tonic-gate 					device_type = DK_CDROM;
12157c478bd9Sstevel@tonic-gate 				}
12167c478bd9Sstevel@tonic-gate 			} else {
12177c478bd9Sstevel@tonic-gate 				device_type = ioctl(t_dev->d_fd,
12187c478bd9Sstevel@tonic-gate 				    DKIOCGMEDIAINFO, &mediainfo);
12197c478bd9Sstevel@tonic-gate 				if (device_type < 0)
12207c478bd9Sstevel@tonic-gate 					device_type = 0;
12217c478bd9Sstevel@tonic-gate 				else
12227c478bd9Sstevel@tonic-gate 					device_type = mediainfo.dki_media_type;
12237c478bd9Sstevel@tonic-gate 			}
12247c478bd9Sstevel@tonic-gate 
1225dd97b1d6Sphitran 			if (!ioctl(t_dev->d_fd, DKIOCREMOVABLE, &removable) &&
1226dd97b1d6Sphitran 			    !ioctl(t_dev->d_fd, DKIOCHOTPLUGGABLE,
1227dd97b1d6Sphitran 			    &hotpluggable)) {
1228dd97b1d6Sphitran 				if (removable || hotpluggable) {
12297c478bd9Sstevel@tonic-gate 					removable_found++;
12307c478bd9Sstevel@tonic-gate 					pname = get_physical_name(sdev);
12317c478bd9Sstevel@tonic-gate 					if (sn) {
12327c478bd9Sstevel@tonic-gate 						(void) printf("  %4d. "
12337c478bd9Sstevel@tonic-gate 						    "Volmgt Node: %s\n",
12347c478bd9Sstevel@tonic-gate 						    removable_found, sn);
12357c478bd9Sstevel@tonic-gate 						(void) printf("        "
12367c478bd9Sstevel@tonic-gate 						    "Logical Node: %s\n", sdev);
12377c478bd9Sstevel@tonic-gate 						(void) printf("        "
12387c478bd9Sstevel@tonic-gate 						    "Physical Node: %s\n",
12397c478bd9Sstevel@tonic-gate 						    pname);
12407c478bd9Sstevel@tonic-gate 					} else {
12417c478bd9Sstevel@tonic-gate 						(void) printf("  %4d. "
12427c478bd9Sstevel@tonic-gate 						    "Logical Node: %s\n",
12437c478bd9Sstevel@tonic-gate 						    removable_found, sdev);
12447c478bd9Sstevel@tonic-gate 						(void) printf("        "
12457c478bd9Sstevel@tonic-gate 						    "Physical Node: %s\n",
12467c478bd9Sstevel@tonic-gate 						    pname);
12477c478bd9Sstevel@tonic-gate 					}
12487c478bd9Sstevel@tonic-gate 					(void) printf("        Connected "
12497c478bd9Sstevel@tonic-gate 					    "Device: %-8.8s %-16.16s "
12507c478bd9Sstevel@tonic-gate 					    "%-4.4s\n",
12517c478bd9Sstevel@tonic-gate 					    &t_dev->d_inq[8],
12527c478bd9Sstevel@tonic-gate 					    &t_dev->d_inq[16],
12537c478bd9Sstevel@tonic-gate 					    &t_dev->d_inq[32]);
12547c478bd9Sstevel@tonic-gate 					(void) printf("        Device "
12557c478bd9Sstevel@tonic-gate 					    "Type: ");
12567c478bd9Sstevel@tonic-gate 				} else
12577c478bd9Sstevel@tonic-gate 					continue;
12587c478bd9Sstevel@tonic-gate 			} else
12597c478bd9Sstevel@tonic-gate 				continue;
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 			switch (device_type) {
12627c478bd9Sstevel@tonic-gate 				case DK_CDROM:
12637c478bd9Sstevel@tonic-gate 					(void) printf("CD Reader\n");
12647c478bd9Sstevel@tonic-gate 					break;
12657c478bd9Sstevel@tonic-gate 				case DK_CDR:
12667c478bd9Sstevel@tonic-gate 				case DK_CDRW:
12677c478bd9Sstevel@tonic-gate 					(void) printf("CD Reader/Writer\n");
12687c478bd9Sstevel@tonic-gate 					break;
12697c478bd9Sstevel@tonic-gate 				case DK_DVDROM:
12707c478bd9Sstevel@tonic-gate 					(void) printf("DVD Reader\n");
12717c478bd9Sstevel@tonic-gate 					break;
12727c478bd9Sstevel@tonic-gate 				case DK_DVDR:
12737c478bd9Sstevel@tonic-gate 				case DK_DVDRAM:
12747c478bd9Sstevel@tonic-gate 					(void) printf("DVD Reader/Writer\n");
12757c478bd9Sstevel@tonic-gate 					break;
12767c478bd9Sstevel@tonic-gate 				case DK_FIXED_DISK:
12777c478bd9Sstevel@tonic-gate 					if (strstr((const char *)
12787c478bd9Sstevel@tonic-gate 					    &t_dev->d_inq[16], "FD") ||
12797c478bd9Sstevel@tonic-gate 					    strstr((const char *)
12807c478bd9Sstevel@tonic-gate 					    &t_dev->d_inq[16], "LS-120"))
12817c478bd9Sstevel@tonic-gate 						(void) printf("Floppy "
12827c478bd9Sstevel@tonic-gate 						    "drive\n");
12837c478bd9Sstevel@tonic-gate 					else
12847c478bd9Sstevel@tonic-gate 						(void) printf("Removable\n");
12857c478bd9Sstevel@tonic-gate 					break;
12867c478bd9Sstevel@tonic-gate 				case DK_FLOPPY:
12877c478bd9Sstevel@tonic-gate 					(void) printf("Floppy drive\n");
12887c478bd9Sstevel@tonic-gate 					break;
12897c478bd9Sstevel@tonic-gate 				case DK_ZIP:
12907c478bd9Sstevel@tonic-gate 					(void) printf("Zip drive\n");
12917c478bd9Sstevel@tonic-gate 					break;
12927c478bd9Sstevel@tonic-gate 				case DK_JAZ:
12937c478bd9Sstevel@tonic-gate 					(void) printf("Jaz drive\n");
12947c478bd9Sstevel@tonic-gate 					break;
12957c478bd9Sstevel@tonic-gate 				default:
12967c478bd9Sstevel@tonic-gate 					(void) printf("<Unknown>\n");
12977c478bd9Sstevel@tonic-gate 					DPRINTF1("\t   %d\n", device_type);
12987c478bd9Sstevel@tonic-gate 					break;
12997c478bd9Sstevel@tonic-gate 			}
13007c478bd9Sstevel@tonic-gate 			get_media_info(t_dev, sdev, pname, sn);
13017c478bd9Sstevel@tonic-gate 		}
13027c478bd9Sstevel@tonic-gate 		fini_device(t_dev);
13037c478bd9Sstevel@tonic-gate 	}
13047c478bd9Sstevel@tonic-gate 
13057c478bd9Sstevel@tonic-gate 	(void) closedir(dir);
13067c478bd9Sstevel@tonic-gate 	return (removable_found);
13077c478bd9Sstevel@tonic-gate }
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate /*
13107c478bd9Sstevel@tonic-gate  * Returns a device_t handle for a node returned by lookup_device()
13117c478bd9Sstevel@tonic-gate  * and takes the user supplied name and stores it inside the node.
13127c478bd9Sstevel@tonic-gate  */
13137c478bd9Sstevel@tonic-gate static device_t *
get_device(char * user_supplied,char * node)13147c478bd9Sstevel@tonic-gate get_device(char *user_supplied, char *node)
13157c478bd9Sstevel@tonic-gate {
13167c478bd9Sstevel@tonic-gate 	device_t *dev;
13177c478bd9Sstevel@tonic-gate 	int fd;
13187c478bd9Sstevel@tonic-gate 	char devnode[PATH_MAX];
13197c478bd9Sstevel@tonic-gate 	int size;
13207c478bd9Sstevel@tonic-gate 
13217c478bd9Sstevel@tonic-gate 	/*
13227c478bd9Sstevel@tonic-gate 	 * we need to resolve any link paths to avoid fake files
13237c478bd9Sstevel@tonic-gate 	 * such as /dev/rdsk/../../export/file.
13247c478bd9Sstevel@tonic-gate 	 */
13257c478bd9Sstevel@tonic-gate 	size = resolvepath(node, devnode, PATH_MAX);
13267c478bd9Sstevel@tonic-gate 	if ((size <= 0) || (size >= (PATH_MAX - 1)))
13277c478bd9Sstevel@tonic-gate 		return (NULL);
13287c478bd9Sstevel@tonic-gate 
13297c478bd9Sstevel@tonic-gate 	/* resolvepath may not return a null terminated string */
13307c478bd9Sstevel@tonic-gate 	devnode[size] = '\0';
13317c478bd9Sstevel@tonic-gate 
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate 	/* the device node must be in /devices/ or /vol/dev/rdsk */
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate 	if ((strncmp(devnode, "/devices/", 9) != 0) &&
13367c478bd9Sstevel@tonic-gate 	    (strncmp(devnode, "/vol/dev/rdsk", 13) != 0))
13377c478bd9Sstevel@tonic-gate 		return (NULL);
13387c478bd9Sstevel@tonic-gate 
1339e3397557Szk 	/* Turn on the privileges. */
1340e3397557Szk 	(void) __priv_bracket(PRIV_ON);
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 	/*
13437c478bd9Sstevel@tonic-gate 	 * Since we are currently running with the user euid it is
13447c478bd9Sstevel@tonic-gate 	 * safe to try to open the file without checking access.
13457c478bd9Sstevel@tonic-gate 	 */
13467c478bd9Sstevel@tonic-gate 
13477c478bd9Sstevel@tonic-gate 	fd = open(devnode, O_RDONLY|O_NDELAY);
13487c478bd9Sstevel@tonic-gate 
1349e3397557Szk 	/* Turn off the privileges. */
1350e3397557Szk 	(void) __priv_bracket(PRIV_OFF);
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate 	if (fd < 0) {
13537c478bd9Sstevel@tonic-gate 		return (NULL);
13547c478bd9Sstevel@tonic-gate 	}
13557c478bd9Sstevel@tonic-gate 
13567c478bd9Sstevel@tonic-gate 	dev = (device_t *)my_zalloc(sizeof (device_t));
13577c478bd9Sstevel@tonic-gate 
13587c478bd9Sstevel@tonic-gate 	dev->d_node = (char *)my_zalloc(strlen(devnode) + 1);
13597c478bd9Sstevel@tonic-gate 	(void) strcpy(dev->d_node, devnode);
13607c478bd9Sstevel@tonic-gate 
13617c478bd9Sstevel@tonic-gate 	dev->d_fd = fd;
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 	dev->d_inq = (uchar_t *)my_zalloc(INQUIRY_DATA_LENGTH);
13647c478bd9Sstevel@tonic-gate 
1365e3397557Szk 	/* Turn on privileges. */
1366e3397557Szk 	(void) __priv_bracket(PRIV_ON);
13677c478bd9Sstevel@tonic-gate 	if (!inquiry(fd, dev->d_inq)) {
13687c478bd9Sstevel@tonic-gate 		DPRINTF1("USCSI ioctl failed %d\n",
13697c478bd9Sstevel@tonic-gate 		    uscsi_error);
13707c478bd9Sstevel@tonic-gate 		free(dev->d_inq);
13717c478bd9Sstevel@tonic-gate 		free(dev->d_node);
13727c478bd9Sstevel@tonic-gate 		(void) close(dev->d_fd);
13737c478bd9Sstevel@tonic-gate 		free(dev);
1374e3397557Szk 		/* Turn off privileges. */
1375e3397557Szk 		(void) __priv_bracket(PRIV_OFF);
13767c478bd9Sstevel@tonic-gate 		return (NULL);
13777c478bd9Sstevel@tonic-gate 	}
1378e3397557Szk 	/* Turn off privileges. */
1379e3397557Szk 	(void) __priv_bracket(PRIV_OFF);
13807c478bd9Sstevel@tonic-gate 
13817c478bd9Sstevel@tonic-gate 	if (user_supplied) {
13827c478bd9Sstevel@tonic-gate 		dev->d_name = (char *)my_zalloc(strlen(user_supplied) + 1);
13837c478bd9Sstevel@tonic-gate 		(void) strcpy(dev->d_name, user_supplied);
13847c478bd9Sstevel@tonic-gate 	}
13857c478bd9Sstevel@tonic-gate 	return (dev);
13867c478bd9Sstevel@tonic-gate }
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate /*
13897c478bd9Sstevel@tonic-gate  * Check for device specific characteristics.
13907c478bd9Sstevel@tonic-gate  */
13917c478bd9Sstevel@tonic-gate int
check_device(device_t * dev,int cond)13927c478bd9Sstevel@tonic-gate check_device(device_t *dev, int cond)
13937c478bd9Sstevel@tonic-gate {
13947c478bd9Sstevel@tonic-gate 	uchar_t page_code[4];
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate 	/* Look at the capabilities page for this information */
13977c478bd9Sstevel@tonic-gate 	if (cond & CHECK_DEVICE_IS_CD_WRITABLE) {
13987c478bd9Sstevel@tonic-gate 		if (get_mode_page(dev->d_fd, 0x2a, 0, 4, page_code) &&
13997c478bd9Sstevel@tonic-gate 		    (page_code[3] & 1)) {
14007c478bd9Sstevel@tonic-gate 			return (1);
14017c478bd9Sstevel@tonic-gate 		}
14027c478bd9Sstevel@tonic-gate 	}
14037c478bd9Sstevel@tonic-gate 
14047c478bd9Sstevel@tonic-gate 	if (cond & CHECK_DEVICE_IS_DVD_WRITABLE) {
14057c478bd9Sstevel@tonic-gate 		if (get_mode_page(dev->d_fd, 0x2a, 0, 4, page_code) &&
14067c478bd9Sstevel@tonic-gate 		    (page_code[3] & 0x10)) {
14077c478bd9Sstevel@tonic-gate 			return (1);
14087c478bd9Sstevel@tonic-gate 		}
14097c478bd9Sstevel@tonic-gate 	}
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 	if (cond & CHECK_DEVICE_IS_DVD_READABLE) {
14127c478bd9Sstevel@tonic-gate 		if (get_mode_page(dev->d_fd, 0x2a, 0, 4, page_code) &&
14137c478bd9Sstevel@tonic-gate 		    (page_code[2] & 0x8)) {
14147c478bd9Sstevel@tonic-gate 			return (1);
14157c478bd9Sstevel@tonic-gate 		}
14167c478bd9Sstevel@tonic-gate 	}
14177c478bd9Sstevel@tonic-gate 
14187c478bd9Sstevel@tonic-gate 	return (0);
14197c478bd9Sstevel@tonic-gate }
14207c478bd9Sstevel@tonic-gate 
14217c478bd9Sstevel@tonic-gate /*
14227c478bd9Sstevel@tonic-gate  * Builds an open()able device path from a user supplied node which can be
14237c478bd9Sstevel@tonic-gate  * of the * form of /dev/[r]dsk/cxtxdx[sx] or cxtxdx[sx] or volmgt-name like
14247c478bd9Sstevel@tonic-gate  * cdrom[n].
14257c478bd9Sstevel@tonic-gate  * Returns the path found in 'found' and returns 1. Otherwise returns 0.
14267c478bd9Sstevel@tonic-gate  */
14277c478bd9Sstevel@tonic-gate int
lookup_device(char * supplied,char * found)14287c478bd9Sstevel@tonic-gate lookup_device(char *supplied, char *found)
14297c478bd9Sstevel@tonic-gate {
14307c478bd9Sstevel@tonic-gate 	struct stat statbuf;
14317c478bd9Sstevel@tonic-gate 	int fd;
14327c478bd9Sstevel@tonic-gate 	char tmpstr[PATH_MAX];
14337c478bd9Sstevel@tonic-gate 
1434e3397557Szk 	/* Turn on privileges */
1435e3397557Szk 	(void) __priv_bracket(PRIV_ON);
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 	/* If everything is fine and proper, no need to analyze */
14384bc0a2efScasper 	if ((stat(supplied, &statbuf) == 0) && S_ISCHR(statbuf.st_mode) &&
14397c478bd9Sstevel@tonic-gate 	    ((fd = open(supplied, O_RDONLY|O_NDELAY)) >= 0)) {
14407c478bd9Sstevel@tonic-gate 		(void) close(fd);
14417c478bd9Sstevel@tonic-gate 		(void) strlcpy(found, supplied, PATH_MAX);
1442e3397557Szk 		/* Turn off privilege */
1443e3397557Szk 		(void) __priv_bracket(PRIV_OFF);
14447c478bd9Sstevel@tonic-gate 		return (1);
14457c478bd9Sstevel@tonic-gate 	}
14467c478bd9Sstevel@tonic-gate 
1447e3397557Szk 	/* Turn off privileges. */
1448e3397557Szk 	(void) __priv_bracket(PRIV_OFF);
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 	if (strncmp(supplied, "/dev/rdsk/", 10) == 0)
14517c478bd9Sstevel@tonic-gate 		return (vol_lookup(supplied, found));
14527c478bd9Sstevel@tonic-gate 	if (strncmp(supplied, "/dev/dsk/", 9) == 0) {
14537c478bd9Sstevel@tonic-gate 		(void) snprintf(tmpstr, PATH_MAX, "/dev/rdsk/%s",
14547c478bd9Sstevel@tonic-gate 		    (char *)strrchr(supplied, '/'));
14557c478bd9Sstevel@tonic-gate 
14567c478bd9Sstevel@tonic-gate 		if ((fd = open(tmpstr, O_RDONLY|O_NDELAY)) >= 0) {
14577c478bd9Sstevel@tonic-gate 			(void) close(fd);
14587c478bd9Sstevel@tonic-gate 			(void) strlcpy(found, supplied, PATH_MAX);
14597c478bd9Sstevel@tonic-gate 			return (1);
14607c478bd9Sstevel@tonic-gate 		}
14617c478bd9Sstevel@tonic-gate 		if ((access(tmpstr, F_OK) == 0) && vol_running)
14627c478bd9Sstevel@tonic-gate 			return (vol_lookup(tmpstr, found));
14637c478bd9Sstevel@tonic-gate 		else
14647c478bd9Sstevel@tonic-gate 			return (0);
14657c478bd9Sstevel@tonic-gate 	}
14667c478bd9Sstevel@tonic-gate 	if ((strncmp(supplied, "cdrom", 5) != 0) &&
14677c478bd9Sstevel@tonic-gate 	    (strlen(supplied) < 32)) {
14687c478bd9Sstevel@tonic-gate 		(void) snprintf(tmpstr, sizeof (tmpstr), "/dev/rdsk/%s",
14697c478bd9Sstevel@tonic-gate 		    supplied);
14707c478bd9Sstevel@tonic-gate 		if (access(tmpstr, F_OK) < 0) {
14717c478bd9Sstevel@tonic-gate 			(void) strcat(tmpstr, "s2");
14727c478bd9Sstevel@tonic-gate 		}
14737c478bd9Sstevel@tonic-gate 		if ((fd = open(tmpstr, O_RDONLY|O_NDELAY)) >= 0) {
14747c478bd9Sstevel@tonic-gate 			(void) close(fd);
14757c478bd9Sstevel@tonic-gate 			(void) strlcpy(found, tmpstr, PATH_MAX);
14767c478bd9Sstevel@tonic-gate 			return (1);
14777c478bd9Sstevel@tonic-gate 		}
14787c478bd9Sstevel@tonic-gate 		if ((access(tmpstr, F_OK) == 0) && vol_running)
14797c478bd9Sstevel@tonic-gate 			return (vol_lookup(tmpstr, found));
14807c478bd9Sstevel@tonic-gate 	}
14817c478bd9Sstevel@tonic-gate 	return (vol_name_to_dev_node(supplied, found));
14827c478bd9Sstevel@tonic-gate }
14837c478bd9Sstevel@tonic-gate 
14847c478bd9Sstevel@tonic-gate int
is_cd(char * node)14857c478bd9Sstevel@tonic-gate is_cd(char *node)
14867c478bd9Sstevel@tonic-gate {
14877c478bd9Sstevel@tonic-gate 	int fd;
14887c478bd9Sstevel@tonic-gate 	struct dk_cinfo cinfo;
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate 	fd = open(node, O_RDONLY|O_NDELAY);
14917c478bd9Sstevel@tonic-gate 	if (fd < 0)
14927c478bd9Sstevel@tonic-gate 		return (0);
14937c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &cinfo) < 0) {
14947c478bd9Sstevel@tonic-gate 		(void) close(fd);
14957c478bd9Sstevel@tonic-gate 		return (0);
14967c478bd9Sstevel@tonic-gate 	}
14977c478bd9Sstevel@tonic-gate 	if (cinfo.dki_ctype != DKC_CDROM)
14987c478bd9Sstevel@tonic-gate 		return (0);
14997c478bd9Sstevel@tonic-gate 	return (1);
15007c478bd9Sstevel@tonic-gate }
15017c478bd9Sstevel@tonic-gate 
15027c478bd9Sstevel@tonic-gate void
print_header(void)15037c478bd9Sstevel@tonic-gate print_header(void)
15047c478bd9Sstevel@tonic-gate {
15057c478bd9Sstevel@tonic-gate 	/* l10n_NOTE : Column spacing should be kept same */
1506*75fafe14SToomas Soome 	(void) printf(gettext("    Node			       "
15077c478bd9Sstevel@tonic-gate 	    "Connected Device"));
15087c478bd9Sstevel@tonic-gate 	/* l10n_NOTE : Column spacing should be kept same */
1509*75fafe14SToomas Soome 	(void) printf(gettext("			Device type\n"));
15107c478bd9Sstevel@tonic-gate 	(void) printf(
15117c478bd9Sstevel@tonic-gate 	    "---------------------------+---------------------------");
15127c478bd9Sstevel@tonic-gate 	(void) printf("-----+----------------\n");
15137c478bd9Sstevel@tonic-gate }
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate void
print_divider(void)15167c478bd9Sstevel@tonic-gate print_divider(void)
15177c478bd9Sstevel@tonic-gate {
15187c478bd9Sstevel@tonic-gate 	(void) printf(
15197c478bd9Sstevel@tonic-gate 	    "---------------------------+---------------------------");
15207c478bd9Sstevel@tonic-gate 	(void) printf("-----+----------------\n");
15217c478bd9Sstevel@tonic-gate }
15227c478bd9Sstevel@tonic-gate 
15237c478bd9Sstevel@tonic-gate static void
fini_device(device_t * dev)15247c478bd9Sstevel@tonic-gate fini_device(device_t *dev)
15257c478bd9Sstevel@tonic-gate {
15267c478bd9Sstevel@tonic-gate 	free(dev->d_inq);
15277c478bd9Sstevel@tonic-gate 	free(dev->d_node);
15287c478bd9Sstevel@tonic-gate 	(void) close(dev->d_fd);
15297c478bd9Sstevel@tonic-gate 	if (dev->d_name)
15307c478bd9Sstevel@tonic-gate 		free(dev->d_name);
15317c478bd9Sstevel@tonic-gate 	free(dev);
15327c478bd9Sstevel@tonic-gate }
15337c478bd9Sstevel@tonic-gate 
15347c478bd9Sstevel@tonic-gate void *
my_zalloc(size_t size)15357c478bd9Sstevel@tonic-gate my_zalloc(size_t size)
15367c478bd9Sstevel@tonic-gate {
15377c478bd9Sstevel@tonic-gate 	void *ret;
15387c478bd9Sstevel@tonic-gate 
15397c478bd9Sstevel@tonic-gate 	ret = malloc(size);
15407c478bd9Sstevel@tonic-gate 	if (ret == NULL) {
15417c478bd9Sstevel@tonic-gate 
15427c478bd9Sstevel@tonic-gate 		/* Lets wait a sec. and try again */
15437c478bd9Sstevel@tonic-gate 		if (errno == EAGAIN) {
15447c478bd9Sstevel@tonic-gate 			(void) sleep(1);
15457c478bd9Sstevel@tonic-gate 			ret = malloc(size);
15467c478bd9Sstevel@tonic-gate 		}
15477c478bd9Sstevel@tonic-gate 
15487c478bd9Sstevel@tonic-gate 		if (ret == NULL) {
15497c478bd9Sstevel@tonic-gate 			(void) err_msg("%s\n", gettext(strerror(errno)));
15507c478bd9Sstevel@tonic-gate 			(void) err_msg(gettext(
15517c478bd9Sstevel@tonic-gate 			    "Memory allocation failure, Exiting...\n"));
15527c478bd9Sstevel@tonic-gate 			exit(1);
15537c478bd9Sstevel@tonic-gate 		}
15547c478bd9Sstevel@tonic-gate 	}
15557c478bd9Sstevel@tonic-gate 	(void) memset(ret, 0, size);
15567c478bd9Sstevel@tonic-gate 	return (ret);
15577c478bd9Sstevel@tonic-gate }
15587c478bd9Sstevel@tonic-gate 
15597c478bd9Sstevel@tonic-gate static int
vol_name_to_dev_node(char * vname,char * found)15607c478bd9Sstevel@tonic-gate vol_name_to_dev_node(char *vname, char *found)
15617c478bd9Sstevel@tonic-gate {
15627c478bd9Sstevel@tonic-gate 	struct stat statbuf;
15637c478bd9Sstevel@tonic-gate 	char *p1;
15647c478bd9Sstevel@tonic-gate 	int i;
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate 	if (vname == NULL)
15677c478bd9Sstevel@tonic-gate 		return (0);
15687c478bd9Sstevel@tonic-gate 	if (vol_running)
15697c478bd9Sstevel@tonic-gate 		(void) volmgt_check(vname);
15707c478bd9Sstevel@tonic-gate 	p1 = media_findname(vname);
15717c478bd9Sstevel@tonic-gate 	if (p1 == NULL)
15727c478bd9Sstevel@tonic-gate 		return (0);
15737c478bd9Sstevel@tonic-gate 	if (stat(p1, &statbuf) < 0) {
15747c478bd9Sstevel@tonic-gate 		free(p1);
15757c478bd9Sstevel@tonic-gate 		return (0);
15767c478bd9Sstevel@tonic-gate 	}
15774bc0a2efScasper 	if (S_ISDIR(statbuf.st_mode)) {
15787c478bd9Sstevel@tonic-gate 		for (i = 0; i < 16; i++) {
15797c478bd9Sstevel@tonic-gate 			(void) snprintf(found, PATH_MAX, "%s/s%d", p1, i);
15807c478bd9Sstevel@tonic-gate 			if (access(found, F_OK) >= 0)
15817c478bd9Sstevel@tonic-gate 				break;
15827c478bd9Sstevel@tonic-gate 		}
15837c478bd9Sstevel@tonic-gate 		if (i == 16) {
15847c478bd9Sstevel@tonic-gate 			free(p1);
15857c478bd9Sstevel@tonic-gate 			return (0);
15867c478bd9Sstevel@tonic-gate 		}
15877c478bd9Sstevel@tonic-gate 	} else {
15887c478bd9Sstevel@tonic-gate 		(void) strlcpy(found, p1, PATH_MAX);
15897c478bd9Sstevel@tonic-gate 	}
15907c478bd9Sstevel@tonic-gate 	free(p1);
15917c478bd9Sstevel@tonic-gate 	return (1);
15927c478bd9Sstevel@tonic-gate }
15937c478bd9Sstevel@tonic-gate 
15947c478bd9Sstevel@tonic-gate /*
15957c478bd9Sstevel@tonic-gate  * Searches for volume manager's equivalent char device for the
15967c478bd9Sstevel@tonic-gate  * supplied pathname which is of the form of /dev/rdsk/cxtxdxsx
15977c478bd9Sstevel@tonic-gate  */
15987c478bd9Sstevel@tonic-gate static int
vol_lookup(char * supplied,char * found)15997c478bd9Sstevel@tonic-gate vol_lookup(char *supplied, char *found)
16007c478bd9Sstevel@tonic-gate {
16017c478bd9Sstevel@tonic-gate 	char tmpstr[PATH_MAX], tmpstr1[PATH_MAX], *p;
16027c478bd9Sstevel@tonic-gate 	int i, ret;
16037c478bd9Sstevel@tonic-gate 
16047c478bd9Sstevel@tonic-gate 	(void) strlcpy(tmpstr, supplied, PATH_MAX);
16057c478bd9Sstevel@tonic-gate 	if ((p = volmgt_symname(tmpstr)) == NULL) {
16067c478bd9Sstevel@tonic-gate 		if (strstr(tmpstr, "s2") != NULL) {
16077c478bd9Sstevel@tonic-gate 			*((char *)(strrchr(tmpstr, 's') + 1)) = 0;
16087c478bd9Sstevel@tonic-gate 			for (i = 0; i < 16; i++) {
16097c478bd9Sstevel@tonic-gate 				(void) snprintf(tmpstr1, PATH_MAX, "%s%d",
16107c478bd9Sstevel@tonic-gate 				    tmpstr, i);
16117c478bd9Sstevel@tonic-gate 				if ((p = volmgt_symname(tmpstr1)) != NULL)
16127c478bd9Sstevel@tonic-gate 					break;
16137c478bd9Sstevel@tonic-gate 			}
16147c478bd9Sstevel@tonic-gate 		} else if (strstr(tmpstr, "p0") != NULL) {
16157c478bd9Sstevel@tonic-gate 			*((char *)(strrchr(tmpstr, 'p') + 1)) = 0;
16167c478bd9Sstevel@tonic-gate 			for (i = 0; i < 5; i++) {
16177c478bd9Sstevel@tonic-gate 				(void) snprintf(tmpstr1, PATH_MAX, "%s%d",
1618afb89a98SPavel Potoplyak 				    tmpstr, i);
16197c478bd9Sstevel@tonic-gate 				if ((p = volmgt_symname(tmpstr1)) != NULL)
16207c478bd9Sstevel@tonic-gate 					break;
16217c478bd9Sstevel@tonic-gate 			}
16227c478bd9Sstevel@tonic-gate 		} else
16237c478bd9Sstevel@tonic-gate 			return (0);
16247c478bd9Sstevel@tonic-gate 		if (p == NULL)
16257c478bd9Sstevel@tonic-gate 			return (0);
16267c478bd9Sstevel@tonic-gate 	}
16277c478bd9Sstevel@tonic-gate 
16287c478bd9Sstevel@tonic-gate 	ret = vol_name_to_dev_node(p, found);
16297c478bd9Sstevel@tonic-gate 	free(p);
16307c478bd9Sstevel@tonic-gate 	return (ret);
16317c478bd9Sstevel@tonic-gate }
16327c478bd9Sstevel@tonic-gate 
16337c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
16347c478bd9Sstevel@tonic-gate void
err_msg(char * fmt,...)16357c478bd9Sstevel@tonic-gate err_msg(char *fmt, ...)
16367c478bd9Sstevel@tonic-gate {
16377c478bd9Sstevel@tonic-gate 	va_list ap;
16387c478bd9Sstevel@tonic-gate 
16397c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
16407c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, fmt, ap);
16417c478bd9Sstevel@tonic-gate 	va_end(ap);
16427c478bd9Sstevel@tonic-gate }
16437c478bd9Sstevel@tonic-gate 
16447c478bd9Sstevel@tonic-gate int
inquiry(int fd,uchar_t * inq)16457c478bd9Sstevel@tonic-gate inquiry(int fd, uchar_t *inq)
16467c478bd9Sstevel@tonic-gate {
16477c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
16487c478bd9Sstevel@tonic-gate 
16497c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
16507c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
16517c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
16527c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = INQUIRY_CMD;
16537c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[4] = INQUIRY_DATA_LENGTH;
16547c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 6;
16557c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)inq;
16567c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = INQUIRY_DATA_LENGTH;
16577c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
16587c478bd9Sstevel@tonic-gate 		return (0);
16597c478bd9Sstevel@tonic-gate 	return (1);
16607c478bd9Sstevel@tonic-gate }
16617c478bd9Sstevel@tonic-gate 
16627c478bd9Sstevel@tonic-gate struct uscsi_cmd *
get_uscsi_cmd(void)16637c478bd9Sstevel@tonic-gate get_uscsi_cmd(void)
16647c478bd9Sstevel@tonic-gate {
16657c478bd9Sstevel@tonic-gate 	(void) memset(&uscmd, 0, sizeof (uscmd));
16667c478bd9Sstevel@tonic-gate 	(void) memset(ucdb, 0, 16);
16677c478bd9Sstevel@tonic-gate 	uscmd.uscsi_cdb = ucdb;
16687c478bd9Sstevel@tonic-gate 	return (&uscmd);
16697c478bd9Sstevel@tonic-gate }
16707c478bd9Sstevel@tonic-gate 
16717c478bd9Sstevel@tonic-gate int
uscsi(int fd,struct uscsi_cmd * scmd)16727c478bd9Sstevel@tonic-gate uscsi(int fd, struct uscsi_cmd *scmd)
16737c478bd9Sstevel@tonic-gate {
16747c478bd9Sstevel@tonic-gate 	int ret, global_rqsense;
16757c478bd9Sstevel@tonic-gate 	int retries, max_retries = 5;
16767c478bd9Sstevel@tonic-gate 	int i;
16777c478bd9Sstevel@tonic-gate 
16787c478bd9Sstevel@tonic-gate 	/* set up for request sense extensions */
16797c478bd9Sstevel@tonic-gate 	if (!(scmd->uscsi_flags & USCSI_RQENABLE)) {
16807c478bd9Sstevel@tonic-gate 		scmd->uscsi_flags |= USCSI_RQENABLE;
16817c478bd9Sstevel@tonic-gate 		scmd->uscsi_rqlen = RQBUFLEN;
16827c478bd9Sstevel@tonic-gate 		scmd->uscsi_rqbuf = rqbuf;
16837c478bd9Sstevel@tonic-gate 		global_rqsense = 1;
16847c478bd9Sstevel@tonic-gate 	} else {
16857c478bd9Sstevel@tonic-gate 		global_rqsense = 0;
16867c478bd9Sstevel@tonic-gate 	}
16877c478bd9Sstevel@tonic-gate 
16887c478bd9Sstevel@tonic-gate 	/*
16897c478bd9Sstevel@tonic-gate 	 * The device may be busy or slow and fail with a not ready status.
16907c478bd9Sstevel@tonic-gate 	 * we'll allow a limited number of retries to give the drive time
16917c478bd9Sstevel@tonic-gate 	 * to recover.
16927c478bd9Sstevel@tonic-gate 	 */
16937c478bd9Sstevel@tonic-gate 	for (retries = 0; retries < max_retries; retries++) {
16947c478bd9Sstevel@tonic-gate 
16957c478bd9Sstevel@tonic-gate 		scmd->uscsi_status = 0;
16967c478bd9Sstevel@tonic-gate 
16977c478bd9Sstevel@tonic-gate 		if (global_rqsense)
16987c478bd9Sstevel@tonic-gate 			(void) memset(rqbuf, 0, RQBUFLEN);
16997c478bd9Sstevel@tonic-gate 
17007c478bd9Sstevel@tonic-gate 		DPRINTF("cmd:[");
17017c478bd9Sstevel@tonic-gate 		for (i = 0; i < scmd->uscsi_cdblen; i++)
17027c478bd9Sstevel@tonic-gate 			DPRINTF1("0x%02x ",
17037c478bd9Sstevel@tonic-gate 			    (uchar_t)scmd->uscsi_cdb[i]);
17047c478bd9Sstevel@tonic-gate 		DPRINTF("]\n");
17057c478bd9Sstevel@tonic-gate 
17067c478bd9Sstevel@tonic-gate 		/*
17077c478bd9Sstevel@tonic-gate 		 * We need to have root privledges in order to use
17087c478bd9Sstevel@tonic-gate 		 * uscsi commands on the device.
17097c478bd9Sstevel@tonic-gate 		 */
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate 		ret = ioctl(fd, USCSICMD, scmd);
17127c478bd9Sstevel@tonic-gate 
17137c478bd9Sstevel@tonic-gate 		/* maintain consistency in case of sgen */
17147c478bd9Sstevel@tonic-gate 		if ((ret == 0) && (scmd->uscsi_status == 2)) {
17157c478bd9Sstevel@tonic-gate 			ret = -1;
17167c478bd9Sstevel@tonic-gate 			errno = EIO;
17177c478bd9Sstevel@tonic-gate 		}
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate 		/* if error and extended request sense, retrieve errors */
17207c478bd9Sstevel@tonic-gate 		if (global_rqsense && (ret < 0) && (scmd->uscsi_status == 2)) {
17217c478bd9Sstevel@tonic-gate 			/*
17227c478bd9Sstevel@tonic-gate 			 * The drive is not ready to recieve commands but
17237c478bd9Sstevel@tonic-gate 			 * may be in the process of becoming ready.
17247c478bd9Sstevel@tonic-gate 			 * sleep for a short time then retry command.
17257c478bd9Sstevel@tonic-gate 			 * SENSE/ASC = 2/4 : not ready
17267c478bd9Sstevel@tonic-gate 			 * ASCQ = 0  Not Reportable.
17277c478bd9Sstevel@tonic-gate 			 * ASCQ = 1  Becoming ready.
17287c478bd9Sstevel@tonic-gate 			 */
17297c478bd9Sstevel@tonic-gate 			if ((SENSE_KEY(rqbuf) == 2) && (ASC(rqbuf) == 4) &&
17307c478bd9Sstevel@tonic-gate 			    ((ASCQ(rqbuf) == 0) || (ASCQ(rqbuf) == 1))) {
17317c478bd9Sstevel@tonic-gate 				total_retries++;
17327c478bd9Sstevel@tonic-gate 				(void) sleep(3);
17337c478bd9Sstevel@tonic-gate 				continue;
17347c478bd9Sstevel@tonic-gate 			}
17357c478bd9Sstevel@tonic-gate 
17367c478bd9Sstevel@tonic-gate 			/*
17377c478bd9Sstevel@tonic-gate 			 * Device is not ready to transmit or a device reset
17387c478bd9Sstevel@tonic-gate 			 * has occurred. wait for a short period of time then
17397c478bd9Sstevel@tonic-gate 			 * retry the command.
17407c478bd9Sstevel@tonic-gate 			 */
17417c478bd9Sstevel@tonic-gate 			if ((SENSE_KEY(rqbuf) == 6) && ((ASC(rqbuf) == 0x28) ||
17427c478bd9Sstevel@tonic-gate 			    (ASC(rqbuf) == 0x29))) {
17437c478bd9Sstevel@tonic-gate 				(void) sleep(3);
17447c478bd9Sstevel@tonic-gate 				total_retries++;
17457c478bd9Sstevel@tonic-gate 				continue;
17467c478bd9Sstevel@tonic-gate 			}
17477c478bd9Sstevel@tonic-gate 
17487c478bd9Sstevel@tonic-gate 			DPRINTF3("cmd: 0x%02x ret:%i status:%02x ",
17497c478bd9Sstevel@tonic-gate 			    (uchar_t)scmd->uscsi_cdb[0], ret,
17507c478bd9Sstevel@tonic-gate 			    scmd->uscsi_status);
17517c478bd9Sstevel@tonic-gate 			DPRINTF3(" sense: %02x ASC: %02x ASCQ:%02x\n",
17527c478bd9Sstevel@tonic-gate 			    (uchar_t)SENSE_KEY(rqbuf),
17537c478bd9Sstevel@tonic-gate 			    (uchar_t)ASC(rqbuf), (uchar_t)ASCQ(rqbuf));
17547c478bd9Sstevel@tonic-gate 		}
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 		/* no errors we'll return */
17577c478bd9Sstevel@tonic-gate 		break;
17587c478bd9Sstevel@tonic-gate 	}
17597c478bd9Sstevel@tonic-gate 
17607c478bd9Sstevel@tonic-gate 	/* store the error status for later debug printing */
17617c478bd9Sstevel@tonic-gate 	if ((ret < 0) && (global_rqsense)) {
17627c478bd9Sstevel@tonic-gate 		uscsi_status = scmd->uscsi_status;
17637c478bd9Sstevel@tonic-gate 		rqstatus = scmd->uscsi_rqstatus;
17647c478bd9Sstevel@tonic-gate 		rqresid = scmd->uscsi_rqresid;
17657c478bd9Sstevel@tonic-gate 
17667c478bd9Sstevel@tonic-gate 	}
17677c478bd9Sstevel@tonic-gate 
17687c478bd9Sstevel@tonic-gate 	DPRINTF1("total retries: %d\n", total_retries);
17697c478bd9Sstevel@tonic-gate 
17707c478bd9Sstevel@tonic-gate 	return (ret);
17717c478bd9Sstevel@tonic-gate }
17727c478bd9Sstevel@tonic-gate 
17737c478bd9Sstevel@tonic-gate /*
17747c478bd9Sstevel@tonic-gate  * will get the mode page only i.e. will strip off the header.
17757c478bd9Sstevel@tonic-gate  */
17767c478bd9Sstevel@tonic-gate int
get_mode_page(int fd,int page_no,int pc,int buf_len,uchar_t * buffer)17777c478bd9Sstevel@tonic-gate get_mode_page(int fd, int page_no, int pc, int buf_len, uchar_t *buffer)
17787c478bd9Sstevel@tonic-gate {
17797c478bd9Sstevel@tonic-gate 	int ret;
17807c478bd9Sstevel@tonic-gate 	uchar_t byte2, *buf;
17817c478bd9Sstevel@tonic-gate 	uint_t header_len, page_len, copy_cnt;
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 	byte2 = (uchar_t)(((pc << 6) & 0xC0) | (page_no & 0x3f));
17847c478bd9Sstevel@tonic-gate 	buf = (uchar_t *)my_zalloc(256);
17857c478bd9Sstevel@tonic-gate 
17867c478bd9Sstevel@tonic-gate 	/* Ask 254 bytes only to make our IDE driver happy */
17877c478bd9Sstevel@tonic-gate 	ret = mode_sense(fd, byte2, 1, 254, buf);
17887c478bd9Sstevel@tonic-gate 	if (ret == 0) {
17897c478bd9Sstevel@tonic-gate 		free(buf);
17907c478bd9Sstevel@tonic-gate 		return (0);
17917c478bd9Sstevel@tonic-gate 	}
17927c478bd9Sstevel@tonic-gate 
17937c478bd9Sstevel@tonic-gate 	header_len = 8 + read_scsi16(&buf[6]);
17947c478bd9Sstevel@tonic-gate 	page_len = buf[header_len + 1] + 2;
17957c478bd9Sstevel@tonic-gate 
17967c478bd9Sstevel@tonic-gate 	copy_cnt = (page_len > buf_len) ? buf_len : page_len;
17977c478bd9Sstevel@tonic-gate 	(void) memcpy(buffer, &buf[header_len], copy_cnt);
17987c478bd9Sstevel@tonic-gate 	free(buf);
17997c478bd9Sstevel@tonic-gate 
18007c478bd9Sstevel@tonic-gate 	return (1);
18017c478bd9Sstevel@tonic-gate }
18027c478bd9Sstevel@tonic-gate 
18037c478bd9Sstevel@tonic-gate int
mode_sense(int fd,uchar_t pc,int dbd,int page_len,uchar_t * buffer)18047c478bd9Sstevel@tonic-gate mode_sense(int fd, uchar_t pc, int dbd, int page_len, uchar_t *buffer)
18057c478bd9Sstevel@tonic-gate {
18067c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
18077c478bd9Sstevel@tonic-gate 
18087c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
18097c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
18107c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = page_len;
18117c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buffer;
18127c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
18137c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 0xa;
18147c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = MODE_SENSE_10_CMD;
18157c478bd9Sstevel@tonic-gate 	if (dbd) {
18167c478bd9Sstevel@tonic-gate 		/* don't return any block descriptors */
18177c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[1] = 0x8;
18187c478bd9Sstevel@tonic-gate 	}
18197c478bd9Sstevel@tonic-gate 	/* the page code we want */
18207c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[2] = pc;
18217c478bd9Sstevel@tonic-gate 	/* allocation length */
18227c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[7] = (page_len >> 8) & 0xff;
18237c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = page_len & 0xff;
18247c478bd9Sstevel@tonic-gate 
18257c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
18267c478bd9Sstevel@tonic-gate 		return (0);
18277c478bd9Sstevel@tonic-gate 	return (1);
18287c478bd9Sstevel@tonic-gate }
18297c478bd9Sstevel@tonic-gate 
18307c478bd9Sstevel@tonic-gate uint16_t
read_scsi16(void * addr)18317c478bd9Sstevel@tonic-gate read_scsi16(void *addr)
18327c478bd9Sstevel@tonic-gate {
18337c478bd9Sstevel@tonic-gate 	uchar_t *ad = (uchar_t *)addr;
18347c478bd9Sstevel@tonic-gate 	uint16_t ret;
18357c478bd9Sstevel@tonic-gate 
18367c478bd9Sstevel@tonic-gate 	ret = ((((uint16_t)ad[0]) << 8) | ad[1]);
18377c478bd9Sstevel@tonic-gate 	return (ret);
18387c478bd9Sstevel@tonic-gate }
18397c478bd9Sstevel@tonic-gate 
18407c478bd9Sstevel@tonic-gate /*
18417c478bd9Sstevel@tonic-gate  * Allocate space for and return a pointer to a string
18427c478bd9Sstevel@tonic-gate  * on the stack.  If the string is null, create
18437c478bd9Sstevel@tonic-gate  * an empty string.
18447c478bd9Sstevel@tonic-gate  * Use destroy_data() to free when no longer used.
18457c478bd9Sstevel@tonic-gate  */
18467c478bd9Sstevel@tonic-gate char *
alloc_string(char * s)1847*75fafe14SToomas Soome alloc_string(char *s)
18487c478bd9Sstevel@tonic-gate {
18497c478bd9Sstevel@tonic-gate 	char    *ns;
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 	if (s == (char *)NULL) {
18527c478bd9Sstevel@tonic-gate 		ns = (char *)my_zalloc(1);
18537c478bd9Sstevel@tonic-gate 	} else {
18547c478bd9Sstevel@tonic-gate 		ns = (char *)my_zalloc(strlen(s) + 1);
18557c478bd9Sstevel@tonic-gate 		(void) strcpy(ns, s);
18567c478bd9Sstevel@tonic-gate 	}
18577c478bd9Sstevel@tonic-gate 	return (ns);
18587c478bd9Sstevel@tonic-gate }
18597c478bd9Sstevel@tonic-gate 
18607c478bd9Sstevel@tonic-gate /*
18617c478bd9Sstevel@tonic-gate  * Follow symbolic links from the logical device name to
18627c478bd9Sstevel@tonic-gate  * the /devfs physical device name.  To be complete, we
18637c478bd9Sstevel@tonic-gate  * handle the case of multiple links.  This function
18647c478bd9Sstevel@tonic-gate  * either returns NULL (no links, or some other error),
18657c478bd9Sstevel@tonic-gate  * or the physical device name, alloc'ed on the heap.
18667c478bd9Sstevel@tonic-gate  *
18677c478bd9Sstevel@tonic-gate  * Note that the standard /devices prefix is stripped from
18687c478bd9Sstevel@tonic-gate  * the final pathname, if present.  The trailing options
18697c478bd9Sstevel@tonic-gate  * are also removed (":c, raw").
18707c478bd9Sstevel@tonic-gate  */
18717c478bd9Sstevel@tonic-gate static char *
get_physical_name(char * path)18727c478bd9Sstevel@tonic-gate get_physical_name(char *path)
18737c478bd9Sstevel@tonic-gate {
18747c478bd9Sstevel@tonic-gate 	struct stat	stbuf;
18757c478bd9Sstevel@tonic-gate 	int		i;
18767c478bd9Sstevel@tonic-gate 	int		level;
18777c478bd9Sstevel@tonic-gate 	char		*p;
18787c478bd9Sstevel@tonic-gate 	char		s[MAXPATHLEN];
18797c478bd9Sstevel@tonic-gate 	char		buf[MAXPATHLEN];
18807c478bd9Sstevel@tonic-gate 	char		dir[MAXPATHLEN];
18817c478bd9Sstevel@tonic-gate 	char		savedir[MAXPATHLEN];
18827c478bd9Sstevel@tonic-gate 	char		*result = NULL;
18837c478bd9Sstevel@tonic-gate 
18847c478bd9Sstevel@tonic-gate 	if (getcwd(savedir, sizeof (savedir)) == NULL) {
18857c478bd9Sstevel@tonic-gate 		DPRINTF1("getcwd() failed - %s\n", strerror(errno));
18867c478bd9Sstevel@tonic-gate 		return (NULL);
18877c478bd9Sstevel@tonic-gate 	}
18887c478bd9Sstevel@tonic-gate 
18897c478bd9Sstevel@tonic-gate 	(void) strcpy(s, path);
18907c478bd9Sstevel@tonic-gate 	if ((p = strrchr(s, '/')) != NULL) {
18917c478bd9Sstevel@tonic-gate 		*p = 0;
18927c478bd9Sstevel@tonic-gate 	}
18937c478bd9Sstevel@tonic-gate 	if (s[0] == 0) {
18947c478bd9Sstevel@tonic-gate 		(void) strcpy(s, "/");
18957c478bd9Sstevel@tonic-gate 	}
18967c478bd9Sstevel@tonic-gate 	if (chdir(s) == -1) {
18977c478bd9Sstevel@tonic-gate 		DPRINTF2("cannot chdir() to %s - %s\n",
1898afb89a98SPavel Potoplyak 		    s, strerror(errno));
18997c478bd9Sstevel@tonic-gate 		goto exit;
19007c478bd9Sstevel@tonic-gate 	}
19017c478bd9Sstevel@tonic-gate 
19027c478bd9Sstevel@tonic-gate 	level = 0;
19037c478bd9Sstevel@tonic-gate 	(void) strcpy(s, path);
19047c478bd9Sstevel@tonic-gate 	for (;;) {
19057c478bd9Sstevel@tonic-gate 		/*
19067c478bd9Sstevel@tonic-gate 		 * See if there's a real file out there.  If not,
19077c478bd9Sstevel@tonic-gate 		 * we have a dangling link and we ignore it.
19087c478bd9Sstevel@tonic-gate 		 */
19097c478bd9Sstevel@tonic-gate 		if (stat(s, &stbuf) == -1) {
19107c478bd9Sstevel@tonic-gate 			goto exit;
19117c478bd9Sstevel@tonic-gate 		}
19127c478bd9Sstevel@tonic-gate 		if (lstat(s, &stbuf) == -1) {
19137c478bd9Sstevel@tonic-gate 			DPRINTF2("%s: lstat() failed - %s\n",
19147c478bd9Sstevel@tonic-gate 			    s, strerror(errno));
19157c478bd9Sstevel@tonic-gate 			goto exit;
19167c478bd9Sstevel@tonic-gate 		}
19177c478bd9Sstevel@tonic-gate 		/*
19187c478bd9Sstevel@tonic-gate 		 * If the file is not a link, we're done one
19197c478bd9Sstevel@tonic-gate 		 * way or the other.  If there were links,
19207c478bd9Sstevel@tonic-gate 		 * return the full pathname of the resulting
19217c478bd9Sstevel@tonic-gate 		 * file.
19227c478bd9Sstevel@tonic-gate 		 */
19237c478bd9Sstevel@tonic-gate 		if (!S_ISLNK(stbuf.st_mode)) {
19247c478bd9Sstevel@tonic-gate 			if (level > 0) {
19257c478bd9Sstevel@tonic-gate 				/*
19267c478bd9Sstevel@tonic-gate 				 * Strip trailing options from the
19277c478bd9Sstevel@tonic-gate 				 * physical device name
19287c478bd9Sstevel@tonic-gate 				 */
19297c478bd9Sstevel@tonic-gate 				if ((p = strrchr(s, ':')) != NULL) {
19307c478bd9Sstevel@tonic-gate 					*p = 0;
19317c478bd9Sstevel@tonic-gate 				}
19327c478bd9Sstevel@tonic-gate 				/*
19337c478bd9Sstevel@tonic-gate 				 * Get the current directory, and
19347c478bd9Sstevel@tonic-gate 				 * glue the pieces together.
19357c478bd9Sstevel@tonic-gate 				 */
19367c478bd9Sstevel@tonic-gate 				if (getcwd(dir, sizeof (dir)) == NULL) {
19377c478bd9Sstevel@tonic-gate 					DPRINTF1("getcwd() failed - %s\n",
1938afb89a98SPavel Potoplyak 					    strerror(errno));
19397c478bd9Sstevel@tonic-gate 					goto exit;
19407c478bd9Sstevel@tonic-gate 				}
19417c478bd9Sstevel@tonic-gate 				(void) strcat(dir, "/");
19427c478bd9Sstevel@tonic-gate 				(void) strcat(dir, s);
19437c478bd9Sstevel@tonic-gate 				/*
19447c478bd9Sstevel@tonic-gate 				 * If we have the standard fixed
19457c478bd9Sstevel@tonic-gate 				 * /devices prefix, remove it.
19467c478bd9Sstevel@tonic-gate 				 */
19477c478bd9Sstevel@tonic-gate 				p = (strstr(dir, DEVFS_PREFIX) == dir) ?
1948afb89a98SPavel Potoplyak 				    dir+strlen(DEVFS_PREFIX) : dir;
19497c478bd9Sstevel@tonic-gate 				result = alloc_string(p);
19507c478bd9Sstevel@tonic-gate 			}
19517c478bd9Sstevel@tonic-gate 			goto exit;
19527c478bd9Sstevel@tonic-gate 		}
19537c478bd9Sstevel@tonic-gate 		i = readlink(s, buf, sizeof (buf));
19547c478bd9Sstevel@tonic-gate 		if (i == -1) {
19557c478bd9Sstevel@tonic-gate 			DPRINTF2("%s: readlink() failed - %s\n",
1956afb89a98SPavel Potoplyak 			    s, strerror(errno));
19577c478bd9Sstevel@tonic-gate 			goto exit;
19587c478bd9Sstevel@tonic-gate 		}
19597c478bd9Sstevel@tonic-gate 		level++;
19607c478bd9Sstevel@tonic-gate 		buf[i] = 0;
19617c478bd9Sstevel@tonic-gate 
19627c478bd9Sstevel@tonic-gate 		/*
19637c478bd9Sstevel@tonic-gate 		 * Break up the pathname into the directory
19647c478bd9Sstevel@tonic-gate 		 * reference, if applicable and simple filename.
19657c478bd9Sstevel@tonic-gate 		 * chdir()'ing to the directory allows us to
19667c478bd9Sstevel@tonic-gate 		 * handle links with relative pathnames correctly.
19677c478bd9Sstevel@tonic-gate 		 */
19687c478bd9Sstevel@tonic-gate 		(void) strcpy(dir, buf);
19697c478bd9Sstevel@tonic-gate 		if ((p = strrchr(dir, '/')) != NULL) {
19707c478bd9Sstevel@tonic-gate 			*p = 0;
19717c478bd9Sstevel@tonic-gate 			if (chdir(dir) == -1) {
19727c478bd9Sstevel@tonic-gate 				DPRINTF2("cannot chdir() to %s - %s\n",
1973afb89a98SPavel Potoplyak 				    dir, strerror(errno));
19747c478bd9Sstevel@tonic-gate 				goto exit;
19757c478bd9Sstevel@tonic-gate 			}
19767c478bd9Sstevel@tonic-gate 			(void) strcpy(s, p+1);
19777c478bd9Sstevel@tonic-gate 		} else {
19787c478bd9Sstevel@tonic-gate 			(void) strcpy(s, buf);
19797c478bd9Sstevel@tonic-gate 		}
19807c478bd9Sstevel@tonic-gate 	}
19817c478bd9Sstevel@tonic-gate 
19827c478bd9Sstevel@tonic-gate exit:
19837c478bd9Sstevel@tonic-gate 	if (chdir(savedir) == -1) {
19847c478bd9Sstevel@tonic-gate 		(void) printf("cannot chdir() to %s - %s\n",
19857c478bd9Sstevel@tonic-gate 		    savedir, strerror(errno));
19867c478bd9Sstevel@tonic-gate 	}
19877c478bd9Sstevel@tonic-gate 
19887c478bd9Sstevel@tonic-gate 	return (result);
19897c478bd9Sstevel@tonic-gate }
19907c478bd9Sstevel@tonic-gate 
19917c478bd9Sstevel@tonic-gate static void
get_media_info(device_t * t_dev,char * sdev,char * pname,char * sn)19927c478bd9Sstevel@tonic-gate get_media_info(device_t *t_dev, char *sdev, char *pname, char *sn)
19937c478bd9Sstevel@tonic-gate {
19947c478bd9Sstevel@tonic-gate 	struct dk_cinfo cinfo;
1995342440ecSPrasad Singamsetty 	struct extvtoc vtocinfo;
19967c478bd9Sstevel@tonic-gate 	float size;
19977c478bd9Sstevel@tonic-gate 	int32_t fd;
19987c478bd9Sstevel@tonic-gate 	smedia_handle_t handle;
19997c478bd9Sstevel@tonic-gate 	struct dk_minfo mediainfo;
20007c478bd9Sstevel@tonic-gate 	int device_type;
20017c478bd9Sstevel@tonic-gate 
20027c478bd9Sstevel@tonic-gate 	device_type = ioctl(t_dev->d_fd, DKIOCGMEDIAINFO, &mediainfo);
20037c478bd9Sstevel@tonic-gate 
20047c478bd9Sstevel@tonic-gate 	/*
20057c478bd9Sstevel@tonic-gate 	 * Determine bus type.
20067c478bd9Sstevel@tonic-gate 	 */
20077c478bd9Sstevel@tonic-gate 	if (!ioctl(t_dev->d_fd, DKIOCINFO, &cinfo)) {
20087c478bd9Sstevel@tonic-gate 		if (strstr(cinfo.dki_cname, "usb") || strstr(pname, "usb")) {
20097c478bd9Sstevel@tonic-gate 			(void) printf("\tBus: USB\n");
20107c478bd9Sstevel@tonic-gate 		} else if (strstr(cinfo.dki_cname, "firewire") ||
20117c478bd9Sstevel@tonic-gate 		    strstr(pname, "firewire")) {
20127c478bd9Sstevel@tonic-gate 			(void) printf("\tBus: Firewire\n");
20137c478bd9Sstevel@tonic-gate 		} else if (strstr(cinfo.dki_cname, "ide") ||
20147c478bd9Sstevel@tonic-gate 		    strstr(pname, "ide")) {
20157c478bd9Sstevel@tonic-gate 			(void) printf("\tBus: IDE\n");
20167c478bd9Sstevel@tonic-gate 		} else if (strstr(cinfo.dki_cname, "scsi") ||
20177c478bd9Sstevel@tonic-gate 		    strstr(pname, "scsi")) {
20187c478bd9Sstevel@tonic-gate 			(void) printf("\tBus: SCSI\n");
20197c478bd9Sstevel@tonic-gate 		} else {
20207c478bd9Sstevel@tonic-gate 			(void) printf("\tBus: <Unknown>\n");
20217c478bd9Sstevel@tonic-gate 		}
20227c478bd9Sstevel@tonic-gate 	} else {
20237c478bd9Sstevel@tonic-gate 		(void) printf("\tBus: <Unknown>\n");
20247c478bd9Sstevel@tonic-gate 	}
20257c478bd9Sstevel@tonic-gate 
20267c478bd9Sstevel@tonic-gate 	/*
20277c478bd9Sstevel@tonic-gate 	 * Calculate size of media.
20287c478bd9Sstevel@tonic-gate 	 */
20297c478bd9Sstevel@tonic-gate 	if (!device_type &&
20307c478bd9Sstevel@tonic-gate 	    (!ioctl(t_dev->d_fd, DKIOCGMEDIAINFO, &mediainfo))) {
20317c478bd9Sstevel@tonic-gate 		size = (mediainfo.dki_lbsize*
20327c478bd9Sstevel@tonic-gate 		    mediainfo.dki_capacity)/(1024.0*1024.0);
20337c478bd9Sstevel@tonic-gate 		if (size < 1000) {
20347c478bd9Sstevel@tonic-gate 			(void) printf("\tSize: %.1f MB\n", size);
20357c478bd9Sstevel@tonic-gate 		} else {
20367c478bd9Sstevel@tonic-gate 			size = size/1000;
20377c478bd9Sstevel@tonic-gate 			(void) printf("\tSize: %.1f GB\n", size);
20387c478bd9Sstevel@tonic-gate 		}
20397c478bd9Sstevel@tonic-gate 	} else {
20407c478bd9Sstevel@tonic-gate 		(void) printf("\tSize: <Unknown>\n");
20417c478bd9Sstevel@tonic-gate 	}
20427c478bd9Sstevel@tonic-gate 
20437c478bd9Sstevel@tonic-gate 	/*
20447c478bd9Sstevel@tonic-gate 	 * Print label.
20457c478bd9Sstevel@tonic-gate 	 */
2046342440ecSPrasad Singamsetty 	if (!device_type && (read_extvtoc(t_dev->d_fd,  &vtocinfo) >= 0)) {
20477c478bd9Sstevel@tonic-gate 		if (*vtocinfo.v_volume) {
20487c478bd9Sstevel@tonic-gate 			(void) printf("\tLabel: %s\n", vtocinfo.v_volume);
20497c478bd9Sstevel@tonic-gate 		} else {
20507c478bd9Sstevel@tonic-gate 			(void) printf("\tLabel: <None>\n");
20517c478bd9Sstevel@tonic-gate 		}
20527c478bd9Sstevel@tonic-gate 	} else {
20537c478bd9Sstevel@tonic-gate 		(void) printf("\tLabel: <Unknown>\n");
20547c478bd9Sstevel@tonic-gate 	}
20557c478bd9Sstevel@tonic-gate 
20567c478bd9Sstevel@tonic-gate 	/*
20577c478bd9Sstevel@tonic-gate 	 * Acess permissions.
20587c478bd9Sstevel@tonic-gate 	 */
20597c478bd9Sstevel@tonic-gate 	if (device_type) {
20607c478bd9Sstevel@tonic-gate 		(void) printf("\tAccess permissions: <Unknown>\n");
20617c478bd9Sstevel@tonic-gate 		return;
20627c478bd9Sstevel@tonic-gate 	}
20637c478bd9Sstevel@tonic-gate 
2064afb89a98SPavel Potoplyak 	(void) fprintf(stdout, gettext("\tAccess permissions: "));
20657c478bd9Sstevel@tonic-gate 	if (sn) {
20667c478bd9Sstevel@tonic-gate 		/*
20677c478bd9Sstevel@tonic-gate 		 * Set dev_name for process_p_flag().
20687c478bd9Sstevel@tonic-gate 		 */
20697c478bd9Sstevel@tonic-gate 		dev_name = sn;
20707c478bd9Sstevel@tonic-gate 		fd = my_open(sn, O_RDONLY|O_NDELAY);
20717c478bd9Sstevel@tonic-gate 	} else {
20727c478bd9Sstevel@tonic-gate 		dev_name = sdev;
20737c478bd9Sstevel@tonic-gate 		fd = my_open(sdev, O_RDONLY|O_NDELAY);
20747c478bd9Sstevel@tonic-gate 	}
20757c478bd9Sstevel@tonic-gate 	if (fd < 0)  {
20767c478bd9Sstevel@tonic-gate 		(void) printf("<Unknown>\n");
20777c478bd9Sstevel@tonic-gate 		DPRINTF("Could not open device.\n");
20787c478bd9Sstevel@tonic-gate 		(void) close(fd);
20797c478bd9Sstevel@tonic-gate 	} else {
20807c478bd9Sstevel@tonic-gate 		/* register the fd with the libsmedia */
20817c478bd9Sstevel@tonic-gate 		handle = smedia_get_handle(fd);
20827c478bd9Sstevel@tonic-gate 		if (handle == NULL) {
20837c478bd9Sstevel@tonic-gate 			(void) printf("<Unknown>\n");
20847c478bd9Sstevel@tonic-gate 			DPRINTF("Failed to get libsmedia handle.\n");
20857c478bd9Sstevel@tonic-gate 			(void) close(fd);
20867c478bd9Sstevel@tonic-gate 		} else {
20877c478bd9Sstevel@tonic-gate 			process_p_flag(handle, fd);
20887c478bd9Sstevel@tonic-gate 		}
20897c478bd9Sstevel@tonic-gate 	}
209026e3e7deSphitran 	/* Clear dev_name */
209126e3e7deSphitran 	dev_name = NULL;
20927c478bd9Sstevel@tonic-gate }
2093