1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate /*LINTLIBRARY*/
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate #include <sys/types.h>
31*0Sstevel@tonic-gate #include <stdio.h>
32*0Sstevel@tonic-gate #include <errno.h>
33*0Sstevel@tonic-gate #include <string.h>
34*0Sstevel@tonic-gate #include <unistd.h>
35*0Sstevel@tonic-gate #include <stdlib.h>
36*0Sstevel@tonic-gate #include <sys/param.h>
37*0Sstevel@tonic-gate #include <sys/stat.h>
38*0Sstevel@tonic-gate #include <sys/sysmacros.h>
39*0Sstevel@tonic-gate #include <sys/vfstab.h>
40*0Sstevel@tonic-gate #include <sys/lofi.h>
41*0Sstevel@tonic-gate #include <sys/ramdisk.h>
42*0Sstevel@tonic-gate #include <sys/fssnap_if.h>
43*0Sstevel@tonic-gate #include "libadm.h"
44*0Sstevel@tonic-gate 
45*0Sstevel@tonic-gate /*
46*0Sstevel@tonic-gate  * Globals:
47*0Sstevel@tonic-gate  *	getfullrawname - returns a fully-qualified raw device name
48*0Sstevel@tonic-gate  *	getfullblkname - returns a fully-qualified block device name
49*0Sstevel@tonic-gate  *
50*0Sstevel@tonic-gate  * These two routines take a device pathname and return corresponding
51*0Sstevel@tonic-gate  * the raw or block device name.
52*0Sstevel@tonic-gate  *
53*0Sstevel@tonic-gate  * First the device name is fully qualified:
54*0Sstevel@tonic-gate  * 	If the device name does not start with a '/' or starts with
55*0Sstevel@tonic-gate  *	'./' then the current working directory is added to the beginning
56*0Sstevel@tonic-gate  *	of the pathname.
57*0Sstevel@tonic-gate  *
58*0Sstevel@tonic-gate  *	If the device name starts with a '../' then all but the last
59*0Sstevel@tonic-gate  *	sub-directory of the current working directory is added to the
60*0Sstevel@tonic-gate  *	the beginning of the pathname.
61*0Sstevel@tonic-gate  *
62*0Sstevel@tonic-gate  * Second if the fully-qualified device name given is the raw/block
63*0Sstevel@tonic-gate  * device that is being asked for then the fully-qualified device name is
64*0Sstevel@tonic-gate  * returned.
65*0Sstevel@tonic-gate  *
66*0Sstevel@tonic-gate  * Third if an entry is found in /etc/vfstab which matches the given name
67*0Sstevel@tonic-gate  * then the corresponding raw/block device is returned.  This allows
68*0Sstevel@tonic-gate  * non-standard names to be converted (.i.e., block device "/dev/joe" can
69*0Sstevel@tonic-gate  * be converted to raw device "/dev/fred", via this mechanism).
70*0Sstevel@tonic-gate  *
71*0Sstevel@tonic-gate  * Last standard names are converted.  Standard names are those
72*0Sstevel@tonic-gate  * with a '/dsk/' for block or '/rdsk/' for raw sub-directory components
73*0Sstevel@tonic-gate  * in the device name. Or, the filename component has an 'r' for raw or
74*0Sstevel@tonic-gate  * no 'r' for block (e.g., rsd0a <=> sd0a).
75*0Sstevel@tonic-gate  *
76*0Sstevel@tonic-gate  * Caveat:
77*0Sstevel@tonic-gate  * It is assumed that the block and raw devices have the
78*0Sstevel@tonic-gate  * same device number, and this is used to verify the conversion
79*0Sstevel@tonic-gate  * happened corretly.  If this happens not to be true, due to mapping
80*0Sstevel@tonic-gate  * of minor numbers or sometheing, then entries can be put in the
81*0Sstevel@tonic-gate  * the '/etc/vfstab' file to over-ride this checking.
82*0Sstevel@tonic-gate  *
83*0Sstevel@tonic-gate  *
84*0Sstevel@tonic-gate  * Return Values:
85*0Sstevel@tonic-gate  * 	raw/block device name	- (depending on which routine is used)
86*0Sstevel@tonic-gate  *	null string		- When the conversion failed
87*0Sstevel@tonic-gate  *	null pointer		- malloc problems
88*0Sstevel@tonic-gate  *
89*0Sstevel@tonic-gate  * It is up to the user of these routines to free the memory, of
90*0Sstevel@tonic-gate  * the device name or null string returned by these library routines,
91*0Sstevel@tonic-gate  * when appropriate by the application.
92*0Sstevel@tonic-gate  */
93*0Sstevel@tonic-gate #define	GET_BLK	0
94*0Sstevel@tonic-gate #define	GET_RAW	1
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate static int test_if_blk(char *, dev_t);
97*0Sstevel@tonic-gate static int test_if_raw(char *, dev_t);
98*0Sstevel@tonic-gate static char *getblkcomplete(char *, struct stat64 *);
99*0Sstevel@tonic-gate static char *getrawcomplete(char *, struct stat64 *);
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate /*
102*0Sstevel@tonic-gate  * getfullname() - Builds a fully qualified pathname.
103*0Sstevel@tonic-gate  *		   This handles . and .. as well.
104*0Sstevel@tonic-gate  *		   NOTE: This is different from realpath(3C) because
105*0Sstevel@tonic-gate  *			 it does not follow links.
106*0Sstevel@tonic-gate  */
107*0Sstevel@tonic-gate static char *
108*0Sstevel@tonic-gate getfullname(char *path)
109*0Sstevel@tonic-gate {
110*0Sstevel@tonic-gate 	char	cwd[MAXPATHLEN];
111*0Sstevel@tonic-gate 	char	*c;
112*0Sstevel@tonic-gate 	char	*wa;
113*0Sstevel@tonic-gate 	size_t	len;
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate 	if (*path == '/')
116*0Sstevel@tonic-gate 		return (strdup(path));
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	if (getcwd(cwd, sizeof (cwd)) == NULL)
119*0Sstevel@tonic-gate 		return (strdup(""));
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	/* handle . and .. */
122*0Sstevel@tonic-gate 	if (strncmp(path, "./", 2) == 0) {
123*0Sstevel@tonic-gate 		/* strip the ./ from the given path */
124*0Sstevel@tonic-gate 		path += 2;
125*0Sstevel@tonic-gate 	} else if (strncmp(path, "../", 3) == 0) {
126*0Sstevel@tonic-gate 		/* strip the last directory component from cwd */
127*0Sstevel@tonic-gate 		c = strrchr(cwd, '/');
128*0Sstevel@tonic-gate 		*c = '\0';
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 		/* strip the ../ from the given path */
131*0Sstevel@tonic-gate 		path += 3;
132*0Sstevel@tonic-gate 	}
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate 	/*
135*0Sstevel@tonic-gate 	 * Adding 2 takes care of slash and null terminator.
136*0Sstevel@tonic-gate 	 */
137*0Sstevel@tonic-gate 	len = strlen(cwd) + strlen(path) + 2;
138*0Sstevel@tonic-gate 	if ((wa = malloc(len)) == NULL)
139*0Sstevel@tonic-gate 		return (NULL);
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate 	(void) strcpy(wa, cwd);
142*0Sstevel@tonic-gate 	(void) strcat(wa, "/");
143*0Sstevel@tonic-gate 	(void) strcat(wa, path);
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 	return (wa);
146*0Sstevel@tonic-gate }
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate /*
149*0Sstevel@tonic-gate  * test the path/fname to see if is blk special
150*0Sstevel@tonic-gate  */
151*0Sstevel@tonic-gate static int
152*0Sstevel@tonic-gate test_if_blk(char *new_path, dev_t raw_dev)
153*0Sstevel@tonic-gate {
154*0Sstevel@tonic-gate 	struct stat64	buf;
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 	/* check if we got a char special file */
157*0Sstevel@tonic-gate 	if (stat64(new_path, &buf) != 0)
158*0Sstevel@tonic-gate 		return (0);
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	if (!S_ISBLK(buf.st_mode))
161*0Sstevel@tonic-gate 		return (0);
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate 	if (raw_dev != buf.st_rdev)
164*0Sstevel@tonic-gate 		return (0);
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	return (1);
167*0Sstevel@tonic-gate }
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate /*
170*0Sstevel@tonic-gate  * test the path/fname to see if is char special
171*0Sstevel@tonic-gate  */
172*0Sstevel@tonic-gate static int
173*0Sstevel@tonic-gate test_if_raw(char *new_path, dev_t blk_dev)
174*0Sstevel@tonic-gate {
175*0Sstevel@tonic-gate 	struct stat64	buf;
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 	/* check if we got a char special file */
178*0Sstevel@tonic-gate 	if (stat64(new_path, &buf) != 0)
179*0Sstevel@tonic-gate 		return (0);
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate 	if (!S_ISCHR(buf.st_mode))
182*0Sstevel@tonic-gate 		return (0);
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	if (blk_dev != buf.st_rdev)
185*0Sstevel@tonic-gate 		return (0);
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate 	return (1);
188*0Sstevel@tonic-gate }
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate /*
191*0Sstevel@tonic-gate  * complete getblkrawname() for blk->raw to handle volmgt devices
192*0Sstevel@tonic-gate  */
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate static char *
195*0Sstevel@tonic-gate getblkcomplete(char *cp, struct stat64 *dat)
196*0Sstevel@tonic-gate {
197*0Sstevel@tonic-gate 	char 		*dp;
198*0Sstevel@tonic-gate 	char		*new_path;
199*0Sstevel@tonic-gate 	char		c;
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 	/* ok, so we either have a bad device or a floppy */
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 	/* try the rfd# form */
204*0Sstevel@tonic-gate 	if ((dp = strstr(cp, "/rfd")) != NULL) {
205*0Sstevel@tonic-gate 		if ((new_path = malloc(strlen(cp))) == NULL)
206*0Sstevel@tonic-gate 			return (NULL);
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate 		c = *++dp;			/* save the 'r' */
209*0Sstevel@tonic-gate 		*dp = '\0';			/* replace it with a null */
210*0Sstevel@tonic-gate 		(void) strcpy(new_path, cp);	/* save first part of it */
211*0Sstevel@tonic-gate 		*dp++ = c;			/* give the 'r' back */
212*0Sstevel@tonic-gate 		(void) strcat(new_path, dp);	/* copy, skipping the 'r' */
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate 		if (test_if_blk(new_path, dat->st_rdev))
215*0Sstevel@tonic-gate 			return (new_path);
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate 		free(new_path);
218*0Sstevel@tonic-gate 		return (strdup(""));
219*0Sstevel@tonic-gate 	}
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 	/* try the rdiskette form */
222*0Sstevel@tonic-gate 	if ((dp = strstr(cp, "/rdiskette")) != NULL) {
223*0Sstevel@tonic-gate 		if ((new_path = malloc(strlen(cp))) == NULL)
224*0Sstevel@tonic-gate 			return (NULL);
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 		c = *++dp;			/* save the 'r' */
227*0Sstevel@tonic-gate 		*dp = '\0';			/* replace it with a null */
228*0Sstevel@tonic-gate 		(void) strcpy(new_path, cp);	/* save first part of it */
229*0Sstevel@tonic-gate 		*dp++ = c;			/* give the 'r' back */
230*0Sstevel@tonic-gate 		(void) strcat(new_path, dp);	/* copy, skipping the 'r' */
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 		if (test_if_blk(new_path, dat->st_rdev))
233*0Sstevel@tonic-gate 			return (new_path);
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 		free(new_path);
236*0Sstevel@tonic-gate 		return (strdup(""));
237*0Sstevel@tonic-gate 	}
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	/* no match found */
240*0Sstevel@tonic-gate 	return (strdup(""));
241*0Sstevel@tonic-gate }
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate /*
244*0Sstevel@tonic-gate  * complete getfullrawname() for raw->blk to handle volmgt devices
245*0Sstevel@tonic-gate  */
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate static char *
248*0Sstevel@tonic-gate getrawcomplete(char *cp, struct stat64 *dat)
249*0Sstevel@tonic-gate {
250*0Sstevel@tonic-gate 	char 		*dp;
251*0Sstevel@tonic-gate 	char		*new_path;
252*0Sstevel@tonic-gate 	char		c;
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 	/* ok, so we either have a bad device or a floppy */
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	/* try the fd# form */
257*0Sstevel@tonic-gate 	if ((dp = strstr(cp, "/fd")) != NULL) {
258*0Sstevel@tonic-gate 		/* malloc path for new_path to hold raw */
259*0Sstevel@tonic-gate 		if ((new_path = malloc(strlen(cp)+2)) == NULL)
260*0Sstevel@tonic-gate 			return (NULL);
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate 		c = *++dp;			/* save the 'f' */
263*0Sstevel@tonic-gate 		*dp = '\0';			/* replace it with a null */
264*0Sstevel@tonic-gate 		(void) strcpy(new_path, cp);	/* save first part of it */
265*0Sstevel@tonic-gate 		*dp = c;			/* put the 'f' back */
266*0Sstevel@tonic-gate 		(void) strcat(new_path, "r");	/* insert an 'r' */
267*0Sstevel@tonic-gate 		(void) strcat(new_path, dp);	/* copy the rest */
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 		if (test_if_raw(new_path, dat->st_rdev))
270*0Sstevel@tonic-gate 			return (new_path);
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 		free(new_path);
273*0Sstevel@tonic-gate 	}
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 	/* try the diskette form */
276*0Sstevel@tonic-gate 	if ((dp = strstr(cp, "/diskette")) != NULL) {
277*0Sstevel@tonic-gate 		/* malloc path for new_path to hold raw */
278*0Sstevel@tonic-gate 		if ((new_path = malloc(strlen(cp)+2)) == NULL)
279*0Sstevel@tonic-gate 			return (NULL);
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 		c = *++dp;			/* save at 'd' */
282*0Sstevel@tonic-gate 		*dp = '\0';			/* replace it with a null */
283*0Sstevel@tonic-gate 		(void) strcpy(new_path, cp);	/* save first part */
284*0Sstevel@tonic-gate 		*dp = c;			/* put the 'd' back */
285*0Sstevel@tonic-gate 		(void) strcat(new_path, "r");	/* insert an 'r' */
286*0Sstevel@tonic-gate 		(void) strcat(new_path, dp);	/* copy the rest */
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate 		if (test_if_raw(new_path, dat->st_rdev))
289*0Sstevel@tonic-gate 			return (new_path);
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 		free(new_path);
292*0Sstevel@tonic-gate 		return (strdup(""));
293*0Sstevel@tonic-gate 	}
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate 	/* failed to build raw name, return null string */
296*0Sstevel@tonic-gate 	return (strdup(""));
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate }
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate static char *
303*0Sstevel@tonic-gate getvfsspecial(char *path, int raw_special)
304*0Sstevel@tonic-gate {
305*0Sstevel@tonic-gate 	FILE		*fp;
306*0Sstevel@tonic-gate 	struct vfstab	vp;
307*0Sstevel@tonic-gate 	struct vfstab	ref_vp;
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	if ((fp = fopen("/etc/vfstab", "r")) == NULL)
310*0Sstevel@tonic-gate 		return (NULL);
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate 	(void) memset(&ref_vp, 0, sizeof (struct vfstab));
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 	if (raw_special)
315*0Sstevel@tonic-gate 		ref_vp.vfs_special = path;
316*0Sstevel@tonic-gate 	else
317*0Sstevel@tonic-gate 		ref_vp.vfs_fsckdev = path;
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	if (getvfsany(fp, &vp, &ref_vp)) {
320*0Sstevel@tonic-gate 		(void) fclose(fp);
321*0Sstevel@tonic-gate 		return (NULL);
322*0Sstevel@tonic-gate 	}
323*0Sstevel@tonic-gate 
324*0Sstevel@tonic-gate 	(void) fclose(fp);
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate 	if (raw_special)
327*0Sstevel@tonic-gate 		return (vp.vfs_fsckdev);
328*0Sstevel@tonic-gate 
329*0Sstevel@tonic-gate 	return (vp.vfs_special);
330*0Sstevel@tonic-gate }
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate /*
333*0Sstevel@tonic-gate  * change the device name to a block device name
334*0Sstevel@tonic-gate  */
335*0Sstevel@tonic-gate char *
336*0Sstevel@tonic-gate getfullblkname(char *cp)
337*0Sstevel@tonic-gate {
338*0Sstevel@tonic-gate 	struct stat64	buf;
339*0Sstevel@tonic-gate 	char		*dp;
340*0Sstevel@tonic-gate 	char		*new_path;
341*0Sstevel@tonic-gate 	dev_t		raw_dev;
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	if (cp == NULL)
344*0Sstevel@tonic-gate 		return (strdup(""));
345*0Sstevel@tonic-gate 
346*0Sstevel@tonic-gate 	/*
347*0Sstevel@tonic-gate 	 * Create a fully qualified name.
348*0Sstevel@tonic-gate 	 */
349*0Sstevel@tonic-gate 	if ((cp = getfullname(cp)) == NULL)
350*0Sstevel@tonic-gate 		return (NULL);
351*0Sstevel@tonic-gate 
352*0Sstevel@tonic-gate 	if (*cp == '\0')
353*0Sstevel@tonic-gate 		return (cp);
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate 	if (stat64(cp, &buf) != 0) {
356*0Sstevel@tonic-gate 		free(cp);
357*0Sstevel@tonic-gate 		return (strdup(""));
358*0Sstevel@tonic-gate 	}
359*0Sstevel@tonic-gate 
360*0Sstevel@tonic-gate 	if (S_ISBLK(buf.st_mode))
361*0Sstevel@tonic-gate 		return (cp);
362*0Sstevel@tonic-gate 
363*0Sstevel@tonic-gate 	if (!S_ISCHR(buf.st_mode)) {
364*0Sstevel@tonic-gate 		free(cp);
365*0Sstevel@tonic-gate 		return (strdup(""));
366*0Sstevel@tonic-gate 	}
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 	if ((dp = getvfsspecial(cp, GET_BLK)) != NULL) {
369*0Sstevel@tonic-gate 		free(cp);
370*0Sstevel@tonic-gate 		return (strdup(dp));
371*0Sstevel@tonic-gate 	}
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	raw_dev = buf.st_rdev;
374*0Sstevel@tonic-gate 
375*0Sstevel@tonic-gate 	/*
376*0Sstevel@tonic-gate 	 * We have a raw device name, go find the block name.
377*0Sstevel@tonic-gate 	 */
378*0Sstevel@tonic-gate 	if ((dp = strstr(cp, "/rdsk/")) == NULL &&
379*0Sstevel@tonic-gate 	    (dp = strstr(cp, "/" LOFI_CHAR_NAME "/")) == NULL &&
380*0Sstevel@tonic-gate 	    (dp = strstr(cp, "/" RD_CHAR_NAME "/")) == NULL &&
381*0Sstevel@tonic-gate 	    (dp = strstr(cp, "/" SNAP_CHAR_NAME "/")) == NULL &&
382*0Sstevel@tonic-gate 	    (dp = strrchr(cp, '/')) == NULL) {
383*0Sstevel@tonic-gate 		/* this is not really possible */
384*0Sstevel@tonic-gate 		free(cp);
385*0Sstevel@tonic-gate 		return (strdup(""));
386*0Sstevel@tonic-gate 	}
387*0Sstevel@tonic-gate 	dp++;
388*0Sstevel@tonic-gate 	if (*dp != 'r') {
389*0Sstevel@tonic-gate 		dp = getblkcomplete(cp, &buf);
390*0Sstevel@tonic-gate 		free(cp);
391*0Sstevel@tonic-gate 		return (dp);
392*0Sstevel@tonic-gate 	}
393*0Sstevel@tonic-gate 	if ((new_path = malloc(strlen(cp))) == NULL) {
394*0Sstevel@tonic-gate 		free(cp);
395*0Sstevel@tonic-gate 		return (NULL);
396*0Sstevel@tonic-gate 	}
397*0Sstevel@tonic-gate 	(void) strncpy(new_path, cp, dp - cp);
398*0Sstevel@tonic-gate 
399*0Sstevel@tonic-gate 	/* fill in the rest of the unraw name */
400*0Sstevel@tonic-gate 	(void) strcpy(new_path + (dp - cp), dp + 1);
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 	if (test_if_blk(new_path, raw_dev)) {
403*0Sstevel@tonic-gate 		free(cp);
404*0Sstevel@tonic-gate 		/* block name was found, return it here */
405*0Sstevel@tonic-gate 		return (new_path);
406*0Sstevel@tonic-gate 	}
407*0Sstevel@tonic-gate 	free(new_path);
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 	dp = getblkcomplete(cp, &buf);
410*0Sstevel@tonic-gate 	free(cp);
411*0Sstevel@tonic-gate 	return (dp);
412*0Sstevel@tonic-gate }
413*0Sstevel@tonic-gate 
414*0Sstevel@tonic-gate /*
415*0Sstevel@tonic-gate  * change the device name to a raw devname
416*0Sstevel@tonic-gate  */
417*0Sstevel@tonic-gate char *
418*0Sstevel@tonic-gate getfullrawname(char *cp)
419*0Sstevel@tonic-gate {
420*0Sstevel@tonic-gate 	struct stat64	buf;
421*0Sstevel@tonic-gate 	char		*dp;
422*0Sstevel@tonic-gate 	char		*new_path;
423*0Sstevel@tonic-gate 	dev_t		blk_dev;
424*0Sstevel@tonic-gate 
425*0Sstevel@tonic-gate 	if (cp == NULL)
426*0Sstevel@tonic-gate 		return (strdup(""));
427*0Sstevel@tonic-gate 
428*0Sstevel@tonic-gate 	/*
429*0Sstevel@tonic-gate 	 * Create a fully qualified name.
430*0Sstevel@tonic-gate 	 */
431*0Sstevel@tonic-gate 	if ((cp = getfullname(cp)) == NULL)
432*0Sstevel@tonic-gate 		return (NULL);
433*0Sstevel@tonic-gate 
434*0Sstevel@tonic-gate 	if (*cp == '\0')
435*0Sstevel@tonic-gate 		return (cp);
436*0Sstevel@tonic-gate 
437*0Sstevel@tonic-gate 	if (stat64(cp, &buf) != 0) {
438*0Sstevel@tonic-gate 		free(cp);
439*0Sstevel@tonic-gate 		return (strdup(""));
440*0Sstevel@tonic-gate 	}
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate 	if (S_ISCHR(buf.st_mode))
443*0Sstevel@tonic-gate 		return (cp);
444*0Sstevel@tonic-gate 
445*0Sstevel@tonic-gate 	if (!S_ISBLK(buf.st_mode)) {
446*0Sstevel@tonic-gate 		free(cp);
447*0Sstevel@tonic-gate 		return (strdup(""));
448*0Sstevel@tonic-gate 	}
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate 	blk_dev = buf.st_rdev;
451*0Sstevel@tonic-gate 
452*0Sstevel@tonic-gate 	if ((dp = getvfsspecial(cp, GET_RAW)) != NULL) {
453*0Sstevel@tonic-gate 		free(cp);
454*0Sstevel@tonic-gate 		return (strdup(dp));
455*0Sstevel@tonic-gate 	}
456*0Sstevel@tonic-gate 
457*0Sstevel@tonic-gate 	/*
458*0Sstevel@tonic-gate 	 * We have a block device name, go find the raw name.
459*0Sstevel@tonic-gate 	 */
460*0Sstevel@tonic-gate 	if ((dp = strstr(cp, "/dsk/")) == NULL &&
461*0Sstevel@tonic-gate 	    (dp = strstr(cp, "/" LOFI_BLOCK_NAME "/")) == NULL &&
462*0Sstevel@tonic-gate 	    (dp = strstr(cp, "/" RD_BLOCK_NAME "/")) == NULL &&
463*0Sstevel@tonic-gate 	    (dp = strstr(cp, "/" SNAP_BLOCK_NAME "/")) == NULL &&
464*0Sstevel@tonic-gate 	    (dp = strrchr(cp, '/')) == NULL) {
465*0Sstevel@tonic-gate 		/* this is not really possible */
466*0Sstevel@tonic-gate 		free(cp);
467*0Sstevel@tonic-gate 		return (strdup(""));
468*0Sstevel@tonic-gate 	}
469*0Sstevel@tonic-gate 	dp++;
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 	if ((new_path = malloc(strlen(cp)+2)) == NULL) {
472*0Sstevel@tonic-gate 		free(cp);
473*0Sstevel@tonic-gate 		return (NULL);
474*0Sstevel@tonic-gate 	}
475*0Sstevel@tonic-gate 	(void) strncpy(new_path, cp, dp - cp);
476*0Sstevel@tonic-gate 	/* fill in the rest of the raw name */
477*0Sstevel@tonic-gate 	new_path[dp - cp] = 'r';
478*0Sstevel@tonic-gate 	(void) strcpy(new_path + (dp - cp) + 1, dp);
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 	if (test_if_raw(new_path, blk_dev)) {
481*0Sstevel@tonic-gate 		free(cp);
482*0Sstevel@tonic-gate 		return (new_path);
483*0Sstevel@tonic-gate 	}
484*0Sstevel@tonic-gate 	free(new_path);
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate 	dp = getrawcomplete(cp, &buf);
487*0Sstevel@tonic-gate 	free(cp);
488*0Sstevel@tonic-gate 	return (dp);
489*0Sstevel@tonic-gate }
490