1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
30*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
31*7c478bd9Sstevel@tonic-gate #include <stdio.h>
32*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
33*7c478bd9Sstevel@tonic-gate #include <string.h>
34*7c478bd9Sstevel@tonic-gate #include <dirent.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
40*7c478bd9Sstevel@tonic-gate #include <unistd.h>
41*7c478bd9Sstevel@tonic-gate #include <devid.h>
42*7c478bd9Sstevel@tonic-gate #include <dirent.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/efi_partition.h>
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #include "libdiskmgt.h"
47*7c478bd9Sstevel@tonic-gate #include "disks_private.h"
48*7c478bd9Sstevel@tonic-gate #include "partition.h"
49*7c478bd9Sstevel@tonic-gate #ifndef VT_ENOTSUP
50*7c478bd9Sstevel@tonic-gate #define	VT_ENOTSUP	(-5)
51*7c478bd9Sstevel@tonic-gate #endif
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate #define	FMT_UNKNOWN	0
54*7c478bd9Sstevel@tonic-gate #define	FMT_VTOC	1
55*7c478bd9Sstevel@tonic-gate #define	FMT_EFI		2
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate static struct inuse_detectors {
58*7c478bd9Sstevel@tonic-gate 	int	(*detectorp)(char *slice, nvlist_t *attrs, int *errp);
59*7c478bd9Sstevel@tonic-gate 	char	*used_by;
60*7c478bd9Sstevel@tonic-gate } detectors[] = {
61*7c478bd9Sstevel@tonic-gate 	{inuse_mnt, DM_USE_MOUNT},
62*7c478bd9Sstevel@tonic-gate 	{inuse_svm, DM_USE_SVM},
63*7c478bd9Sstevel@tonic-gate 	{inuse_lu, DM_USE_LU},
64*7c478bd9Sstevel@tonic-gate 	{inuse_dump, DM_USE_DUMP},
65*7c478bd9Sstevel@tonic-gate 	{inuse_vxvm, DM_USE_VXVM},
66*7c478bd9Sstevel@tonic-gate 	{inuse_fs, DM_USE_FS},  /* fs should always be last */
67*7c478bd9Sstevel@tonic-gate 	{NULL, NULL}
68*7c478bd9Sstevel@tonic-gate };
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate static int	add_inuse(char *name, nvlist_t *attrs);
71*7c478bd9Sstevel@tonic-gate static int	desc_ok(descriptor_t *dp);
72*7c478bd9Sstevel@tonic-gate static void	dsk2rdsk(char *dsk, char *rdsk, int size);
73*7c478bd9Sstevel@tonic-gate static int	get_attrs(descriptor_t *dp, int fd,  nvlist_t *attrs);
74*7c478bd9Sstevel@tonic-gate static descriptor_t **get_fixed_assocs(descriptor_t *desc, int *errp);
75*7c478bd9Sstevel@tonic-gate static descriptor_t **get_removable_assocs(descriptor_t *desc, char *volm_path,
76*7c478bd9Sstevel@tonic-gate 		    int *errp);
77*7c478bd9Sstevel@tonic-gate static int	get_slice_num(slice_t *devp);
78*7c478bd9Sstevel@tonic-gate static int	match_fixed_name(disk_t *dp, char *name, int *errp);
79*7c478bd9Sstevel@tonic-gate static int	match_removable_name(disk_t *dp, char *name, int *errp);
80*7c478bd9Sstevel@tonic-gate static int	make_fixed_descriptors(disk_t *dp);
81*7c478bd9Sstevel@tonic-gate static int	make_removable_descriptors(disk_t *dp);
82*7c478bd9Sstevel@tonic-gate static int	make_volm_dir_descriptors(disk_t *dp, int fd,
83*7c478bd9Sstevel@tonic-gate 		    char *volm_path);
84*7c478bd9Sstevel@tonic-gate static int	num_removable_slices(int fd, struct stat *bufp,
85*7c478bd9Sstevel@tonic-gate 		    char *volm_path);
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate descriptor_t **
88*7c478bd9Sstevel@tonic-gate slice_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type,
89*7c478bd9Sstevel@tonic-gate     int *errp)
90*7c478bd9Sstevel@tonic-gate {
91*7c478bd9Sstevel@tonic-gate 	if (!desc_ok(desc)) {
92*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
93*7c478bd9Sstevel@tonic-gate 	    return (NULL);
94*7c478bd9Sstevel@tonic-gate 	}
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 	switch (type) {
97*7c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
98*7c478bd9Sstevel@tonic-gate 	    return (media_get_assocs(desc, errp));
99*7c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
100*7c478bd9Sstevel@tonic-gate 	    return (partition_get_assocs(desc, errp));
101*7c478bd9Sstevel@tonic-gate 	}
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	*errp = EINVAL;
104*7c478bd9Sstevel@tonic-gate 	return (NULL);
105*7c478bd9Sstevel@tonic-gate }
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate /*
108*7c478bd9Sstevel@tonic-gate  * This is called by media/partition to get the slice descriptors for the given
109*7c478bd9Sstevel@tonic-gate  * media/partition descriptor.
110*7c478bd9Sstevel@tonic-gate  * For media, just get the slices, but for a partition, it must be a solaris
111*7c478bd9Sstevel@tonic-gate  * partition and if there are active partitions, it must be the active one.
112*7c478bd9Sstevel@tonic-gate  */
113*7c478bd9Sstevel@tonic-gate descriptor_t **
114*7c478bd9Sstevel@tonic-gate slice_get_assocs(descriptor_t *desc, int *errp)
115*7c478bd9Sstevel@tonic-gate {
116*7c478bd9Sstevel@tonic-gate 	int		under_volm = 0;
117*7c478bd9Sstevel@tonic-gate 	char		volm_path[MAXPATHLEN];
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	/* Just check the first drive name. */
120*7c478bd9Sstevel@tonic-gate 	if (desc->p.disk->aliases == NULL) {
121*7c478bd9Sstevel@tonic-gate 	    *errp = 0;
122*7c478bd9Sstevel@tonic-gate 	    return (libdiskmgt_empty_desc_array(errp));
123*7c478bd9Sstevel@tonic-gate 	}
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate 	if (desc->p.disk->removable) {
126*7c478bd9Sstevel@tonic-gate 	    if ((under_volm = media_get_volm_path(desc->p.disk, volm_path,
127*7c478bd9Sstevel@tonic-gate 		sizeof (volm_path)))) {
128*7c478bd9Sstevel@tonic-gate 		if (volm_path[0] == 0) {
129*7c478bd9Sstevel@tonic-gate 		    /* no media */
130*7c478bd9Sstevel@tonic-gate 		    *errp = 0;
131*7c478bd9Sstevel@tonic-gate 		    return (libdiskmgt_empty_desc_array(errp));
132*7c478bd9Sstevel@tonic-gate 		}
133*7c478bd9Sstevel@tonic-gate 	    }
134*7c478bd9Sstevel@tonic-gate 	}
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	if (desc->p.disk->removable) {
137*7c478bd9Sstevel@tonic-gate 	    if (under_volm) {
138*7c478bd9Sstevel@tonic-gate 		return (get_removable_assocs(desc, volm_path, errp));
139*7c478bd9Sstevel@tonic-gate 	    } else {
140*7c478bd9Sstevel@tonic-gate 		return (get_fixed_assocs(desc, errp));
141*7c478bd9Sstevel@tonic-gate 	    }
142*7c478bd9Sstevel@tonic-gate 	} else {
143*7c478bd9Sstevel@tonic-gate 	    return (get_fixed_assocs(desc, errp));
144*7c478bd9Sstevel@tonic-gate 	}
145*7c478bd9Sstevel@tonic-gate }
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate nvlist_t *
148*7c478bd9Sstevel@tonic-gate slice_get_attributes(descriptor_t *dp, int *errp)
149*7c478bd9Sstevel@tonic-gate {
150*7c478bd9Sstevel@tonic-gate 	nvlist_t	*attrs = NULL;
151*7c478bd9Sstevel@tonic-gate 	int		fd;
152*7c478bd9Sstevel@tonic-gate 	char		devpath[MAXPATHLEN];
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	if (!desc_ok(dp)) {
155*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
156*7c478bd9Sstevel@tonic-gate 	    return (NULL);
157*7c478bd9Sstevel@tonic-gate 	}
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
160*7c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
161*7c478bd9Sstevel@tonic-gate 	    return (NULL);
162*7c478bd9Sstevel@tonic-gate 	}
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	/* dp->name is /dev/dsk, need to convert back to /dev/rdsk */
165*7c478bd9Sstevel@tonic-gate 	dsk2rdsk(dp->name, devpath, sizeof (devpath));
166*7c478bd9Sstevel@tonic-gate 	fd = open(devpath, O_RDONLY|O_NDELAY);
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	if ((*errp = get_attrs(dp, fd, attrs)) != 0) {
169*7c478bd9Sstevel@tonic-gate 	    nvlist_free(attrs);
170*7c478bd9Sstevel@tonic-gate 	    attrs = NULL;
171*7c478bd9Sstevel@tonic-gate 	}
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	if (fd >= 0) {
174*7c478bd9Sstevel@tonic-gate 	    (void) close(fd);
175*7c478bd9Sstevel@tonic-gate 	}
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	return (attrs);
178*7c478bd9Sstevel@tonic-gate }
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate /*
181*7c478bd9Sstevel@tonic-gate  * Look for the slice by the slice devpath.
182*7c478bd9Sstevel@tonic-gate  */
183*7c478bd9Sstevel@tonic-gate descriptor_t *
184*7c478bd9Sstevel@tonic-gate slice_get_descriptor_by_name(char *name, int *errp)
185*7c478bd9Sstevel@tonic-gate {
186*7c478bd9Sstevel@tonic-gate 	int		found = 0;
187*7c478bd9Sstevel@tonic-gate 	disk_t		*dp;
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	for (dp = cache_get_disklist(); dp != NULL; dp = dp->next) {
190*7c478bd9Sstevel@tonic-gate 	    if (dp->removable) {
191*7c478bd9Sstevel@tonic-gate 		found = match_removable_name(dp, name, errp);
192*7c478bd9Sstevel@tonic-gate 	    } else {
193*7c478bd9Sstevel@tonic-gate 		found = match_fixed_name(dp, name, errp);
194*7c478bd9Sstevel@tonic-gate 	    }
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	    if (found) {
197*7c478bd9Sstevel@tonic-gate 		char	mname[MAXPATHLEN];
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 		if (*errp != 0) {
200*7c478bd9Sstevel@tonic-gate 		    return (NULL);
201*7c478bd9Sstevel@tonic-gate 		}
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 		mname[0] = 0;
204*7c478bd9Sstevel@tonic-gate 		(void) media_read_name(dp, mname, sizeof (mname));
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 		return (cache_get_desc(DM_SLICE, dp, name, mname, errp));
207*7c478bd9Sstevel@tonic-gate 	    }
208*7c478bd9Sstevel@tonic-gate 	}
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	*errp = ENODEV;
211*7c478bd9Sstevel@tonic-gate 	return (NULL);
212*7c478bd9Sstevel@tonic-gate }
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
215*7c478bd9Sstevel@tonic-gate descriptor_t **
216*7c478bd9Sstevel@tonic-gate slice_get_descriptors(int filter[], int *errp)
217*7c478bd9Sstevel@tonic-gate {
218*7c478bd9Sstevel@tonic-gate 	return (cache_get_descriptors(DM_SLICE, errp));
219*7c478bd9Sstevel@tonic-gate }
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate char *
222*7c478bd9Sstevel@tonic-gate slice_get_name(descriptor_t *desc)
223*7c478bd9Sstevel@tonic-gate {
224*7c478bd9Sstevel@tonic-gate 	return (desc->name);
225*7c478bd9Sstevel@tonic-gate }
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate nvlist_t *
228*7c478bd9Sstevel@tonic-gate slice_get_stats(descriptor_t *dp, int stat_type, int *errp)
229*7c478bd9Sstevel@tonic-gate {
230*7c478bd9Sstevel@tonic-gate 	nvlist_t	*stats;
231*7c478bd9Sstevel@tonic-gate 	char		*str;
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	if (stat_type != DM_SLICE_STAT_USE) {
234*7c478bd9Sstevel@tonic-gate 	    *errp = EINVAL;
235*7c478bd9Sstevel@tonic-gate 	    return (NULL);
236*7c478bd9Sstevel@tonic-gate 	}
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	*errp = 0;
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&stats, NVATTRS_STAT, 0) != 0) {
241*7c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
242*7c478bd9Sstevel@tonic-gate 	    return (NULL);
243*7c478bd9Sstevel@tonic-gate 	}
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	if ((*errp = add_inuse(dp->name, stats)) != 0) {
246*7c478bd9Sstevel@tonic-gate 	    return (NULL);
247*7c478bd9Sstevel@tonic-gate 	}
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 	/* if no cluster use, check for a use of the local name */
250*7c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(stats, DM_USED_BY, &str) != 0) {
251*7c478bd9Sstevel@tonic-gate 	    disk_t	*diskp;
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 	    diskp = dp->p.disk;
254*7c478bd9Sstevel@tonic-gate 	    if (diskp->aliases != NULL && diskp->aliases->cluster) {
255*7c478bd9Sstevel@tonic-gate 		slice_t		*sp;
256*7c478bd9Sstevel@tonic-gate 		int		snum = -1;
257*7c478bd9Sstevel@tonic-gate 		struct dk_minfo	minfo;
258*7c478bd9Sstevel@tonic-gate 		struct dk_cinfo	dkinfo;
259*7c478bd9Sstevel@tonic-gate 		char		devpath[MAXPATHLEN];
260*7c478bd9Sstevel@tonic-gate 		int		fd;
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 		/* dp->name is /dev/dsk, need to convert back to /dev/rdsk */
263*7c478bd9Sstevel@tonic-gate 		dsk2rdsk(dp->name, devpath, sizeof (devpath));
264*7c478bd9Sstevel@tonic-gate 		fd = open(devpath, O_RDONLY|O_NDELAY);
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 		if (fd >= 0 && media_read_info(fd, &minfo) &&
267*7c478bd9Sstevel@tonic-gate 		    ioctl(fd, DKIOCINFO, &dkinfo) >= 0) {
268*7c478bd9Sstevel@tonic-gate 		    snum = dkinfo.dki_partition;
269*7c478bd9Sstevel@tonic-gate 		}
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 		if (fd >= 0) {
272*7c478bd9Sstevel@tonic-gate 		    (void) close(fd);
273*7c478bd9Sstevel@tonic-gate 		}
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 		if (snum >= 0) {
276*7c478bd9Sstevel@tonic-gate 		    for (sp = diskp->aliases->orig_paths; sp != NULL;
277*7c478bd9Sstevel@tonic-gate 			sp = sp->next) {
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 			if (sp->slice_num == snum) {
280*7c478bd9Sstevel@tonic-gate 			    char	localpath[MAXPATHLEN];
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 			    slice_rdsk2dsk(sp->devpath, localpath,
283*7c478bd9Sstevel@tonic-gate 				sizeof (localpath));
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 			    if ((*errp = add_inuse(localpath, stats)) != 0) {
286*7c478bd9Sstevel@tonic-gate 				return (NULL);
287*7c478bd9Sstevel@tonic-gate 			    }
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 			    break;
290*7c478bd9Sstevel@tonic-gate 			}
291*7c478bd9Sstevel@tonic-gate 		    }
292*7c478bd9Sstevel@tonic-gate 		}
293*7c478bd9Sstevel@tonic-gate 	    }
294*7c478bd9Sstevel@tonic-gate 	}
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 	return (stats);
297*7c478bd9Sstevel@tonic-gate }
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate /*
300*7c478bd9Sstevel@tonic-gate  * A slice descriptor points to a disk, the name is the devpath and the
301*7c478bd9Sstevel@tonic-gate  * secondary name is the media name.
302*7c478bd9Sstevel@tonic-gate  */
303*7c478bd9Sstevel@tonic-gate int
304*7c478bd9Sstevel@tonic-gate slice_make_descriptors()
305*7c478bd9Sstevel@tonic-gate {
306*7c478bd9Sstevel@tonic-gate 	disk_t		*dp;
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	dp = cache_get_disklist();
309*7c478bd9Sstevel@tonic-gate 	while (dp != NULL) {
310*7c478bd9Sstevel@tonic-gate 	    int	error;
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	    if (dp->removable) {
313*7c478bd9Sstevel@tonic-gate 		error = make_removable_descriptors(dp);
314*7c478bd9Sstevel@tonic-gate 	    } else {
315*7c478bd9Sstevel@tonic-gate 		error = make_fixed_descriptors(dp);
316*7c478bd9Sstevel@tonic-gate 	    }
317*7c478bd9Sstevel@tonic-gate 	    if (error != 0) {
318*7c478bd9Sstevel@tonic-gate 		return (error);
319*7c478bd9Sstevel@tonic-gate 	    }
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	    dp = dp->next;
322*7c478bd9Sstevel@tonic-gate 	}
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 	return (0);
325*7c478bd9Sstevel@tonic-gate }
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate /* convert rdsk paths to dsk paths */
328*7c478bd9Sstevel@tonic-gate void
329*7c478bd9Sstevel@tonic-gate slice_rdsk2dsk(char *rdsk, char *dsk, int size)
330*7c478bd9Sstevel@tonic-gate {
331*7c478bd9Sstevel@tonic-gate 	char	*strp;
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(dsk, rdsk, size);
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	if ((strp = strstr(dsk, "/rdsk/")) == NULL) {
336*7c478bd9Sstevel@tonic-gate 	    /* not rdsk, check for floppy */
337*7c478bd9Sstevel@tonic-gate 	    strp = strstr(dsk, "/rdiskette");
338*7c478bd9Sstevel@tonic-gate 	}
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 	if (strp != NULL) {
341*7c478bd9Sstevel@tonic-gate 	    strp++;	/* move ptr to the r in rdsk or rdiskette */
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 	    /* move the succeeding chars over by one */
344*7c478bd9Sstevel@tonic-gate 	    do {
345*7c478bd9Sstevel@tonic-gate 		*strp = *(strp + 1);
346*7c478bd9Sstevel@tonic-gate 		strp++;
347*7c478bd9Sstevel@tonic-gate 	    } while (*strp);
348*7c478bd9Sstevel@tonic-gate 	}
349*7c478bd9Sstevel@tonic-gate }
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate /*
352*7c478bd9Sstevel@tonic-gate  * Check if/how the slice is used.
353*7c478bd9Sstevel@tonic-gate  */
354*7c478bd9Sstevel@tonic-gate static int
355*7c478bd9Sstevel@tonic-gate add_inuse(char *name, nvlist_t *attrs)
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate 	int	i;
358*7c478bd9Sstevel@tonic-gate 	int	error;
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	for (i = 0; detectors[i].detectorp != NULL; i ++) {
361*7c478bd9Sstevel@tonic-gate 	    if ((detectors[i].detectorp)(name, attrs, &error) || error != 0) {
362*7c478bd9Sstevel@tonic-gate 		if (error != 0) {
363*7c478bd9Sstevel@tonic-gate 		    return (error);
364*7c478bd9Sstevel@tonic-gate 		}
365*7c478bd9Sstevel@tonic-gate 		break;
366*7c478bd9Sstevel@tonic-gate 	    }
367*7c478bd9Sstevel@tonic-gate 	}
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 	return (0);
370*7c478bd9Sstevel@tonic-gate }
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate /* return 1 if the slice descriptor is still valid, 0 if not. */
373*7c478bd9Sstevel@tonic-gate static int
374*7c478bd9Sstevel@tonic-gate desc_ok(descriptor_t *dp)
375*7c478bd9Sstevel@tonic-gate {
376*7c478bd9Sstevel@tonic-gate 	/* First verify the media name for removable media */
377*7c478bd9Sstevel@tonic-gate 	if (dp->p.disk->removable) {
378*7c478bd9Sstevel@tonic-gate 	    char	mname[MAXPATHLEN];
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate 	    if (!media_read_name(dp->p.disk, mname, sizeof (mname))) {
381*7c478bd9Sstevel@tonic-gate 		return (0);
382*7c478bd9Sstevel@tonic-gate 	    }
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	    if (mname[0] == 0) {
385*7c478bd9Sstevel@tonic-gate 		return (libdiskmgt_str_eq(dp->secondary_name, NULL));
386*7c478bd9Sstevel@tonic-gate 	    } else {
387*7c478bd9Sstevel@tonic-gate 		return (libdiskmgt_str_eq(dp->secondary_name, mname));
388*7c478bd9Sstevel@tonic-gate 	    }
389*7c478bd9Sstevel@tonic-gate 	}
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	/*
392*7c478bd9Sstevel@tonic-gate 	 * We could verify the slice is still there, but other code down the
393*7c478bd9Sstevel@tonic-gate 	 * line already does these checks (e.g. see get_attrs).
394*7c478bd9Sstevel@tonic-gate 	 */
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 	return (1);
397*7c478bd9Sstevel@tonic-gate }
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate /* convert dsk paths to rdsk paths */
400*7c478bd9Sstevel@tonic-gate static void
401*7c478bd9Sstevel@tonic-gate dsk2rdsk(char *dsk, char *rdsk, int size)
402*7c478bd9Sstevel@tonic-gate {
403*7c478bd9Sstevel@tonic-gate 	char	*slashp;
404*7c478bd9Sstevel@tonic-gate 	size_t	len;
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(rdsk, dsk, size);
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 	/* make sure there is enough room to add the r to dsk */
409*7c478bd9Sstevel@tonic-gate 	len = strlen(dsk);
410*7c478bd9Sstevel@tonic-gate 	if (len + 2 > size) {
411*7c478bd9Sstevel@tonic-gate 	    return;
412*7c478bd9Sstevel@tonic-gate 	}
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 	if ((slashp = strstr(rdsk, "/dsk/")) == NULL) {
415*7c478bd9Sstevel@tonic-gate 	    /* not dsk, check for floppy */
416*7c478bd9Sstevel@tonic-gate 	    slashp = strstr(rdsk, "/diskette");
417*7c478bd9Sstevel@tonic-gate 	}
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 	if (slashp != NULL) {
420*7c478bd9Sstevel@tonic-gate 	    char	*endp;
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	    endp = rdsk + len;	/* point to terminating 0 */
423*7c478bd9Sstevel@tonic-gate 	    /* move the succeeding chars over by one */
424*7c478bd9Sstevel@tonic-gate 	    do {
425*7c478bd9Sstevel@tonic-gate 		*(endp + 1) = *endp;
426*7c478bd9Sstevel@tonic-gate 		endp--;
427*7c478bd9Sstevel@tonic-gate 	    } while (endp != slashp);
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate 	    *(endp + 1) = 'r';
430*7c478bd9Sstevel@tonic-gate 	}
431*7c478bd9Sstevel@tonic-gate }
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate static int
434*7c478bd9Sstevel@tonic-gate get_attrs(descriptor_t *dp, int fd,  nvlist_t *attrs)
435*7c478bd9Sstevel@tonic-gate {
436*7c478bd9Sstevel@tonic-gate 	struct dk_minfo	minfo;
437*7c478bd9Sstevel@tonic-gate 	int		status;
438*7c478bd9Sstevel@tonic-gate 	int		data_format = FMT_UNKNOWN;
439*7c478bd9Sstevel@tonic-gate 	int		snum = -1;
440*7c478bd9Sstevel@tonic-gate 	int		error;
441*7c478bd9Sstevel@tonic-gate 	struct vtoc	vtoc;
442*7c478bd9Sstevel@tonic-gate 	struct dk_gpt	*efip;
443*7c478bd9Sstevel@tonic-gate 	struct dk_cinfo	dkinfo;
444*7c478bd9Sstevel@tonic-gate 	disk_t		*diskp;
445*7c478bd9Sstevel@tonic-gate 	char		localpath[MAXPATHLEN];
446*7c478bd9Sstevel@tonic-gate 	int		cooked_fd;
447*7c478bd9Sstevel@tonic-gate 	struct stat	buf;
448*7c478bd9Sstevel@tonic-gate 	int		mntpnt = 0;
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 	if (fd < 0) {
451*7c478bd9Sstevel@tonic-gate 	    return (ENODEV);
452*7c478bd9Sstevel@tonic-gate 	}
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 	/* First make sure media is inserted and spun up. */
455*7c478bd9Sstevel@tonic-gate 	if (!media_read_info(fd, &minfo)) {
456*7c478bd9Sstevel@tonic-gate #ifdef i386
457*7c478bd9Sstevel@tonic-gate 	    /* XXX Work around bug 4725434 */
458*7c478bd9Sstevel@tonic-gate 	    if (dp->p.disk->removable)
459*7c478bd9Sstevel@tonic-gate #endif
460*7c478bd9Sstevel@tonic-gate 	    return (ENODEV);
461*7c478bd9Sstevel@tonic-gate 	}
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 	if ((status = read_vtoc(fd, &vtoc)) >= 0) {
464*7c478bd9Sstevel@tonic-gate 	    data_format = FMT_VTOC;
465*7c478bd9Sstevel@tonic-gate 	} else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) {
466*7c478bd9Sstevel@tonic-gate 	    data_format = FMT_EFI;
467*7c478bd9Sstevel@tonic-gate 	    if (nvlist_add_boolean(attrs, DM_EFI) != 0) {
468*7c478bd9Sstevel@tonic-gate 		efi_free(efip);
469*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
470*7c478bd9Sstevel@tonic-gate 	    }
471*7c478bd9Sstevel@tonic-gate 	}
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 	if (data_format == FMT_UNKNOWN) {
474*7c478bd9Sstevel@tonic-gate 	    return (ENODEV);
475*7c478bd9Sstevel@tonic-gate 	}
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &dkinfo) >= 0) {
478*7c478bd9Sstevel@tonic-gate 	    snum = dkinfo.dki_partition;
479*7c478bd9Sstevel@tonic-gate 	}
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 	/* check the slice */
482*7c478bd9Sstevel@tonic-gate 	if (data_format == FMT_VTOC) {
483*7c478bd9Sstevel@tonic-gate 	    if (snum < 0 || snum >= vtoc.v_nparts ||
484*7c478bd9Sstevel@tonic-gate 		vtoc.v_part[snum].p_size == 0) {
485*7c478bd9Sstevel@tonic-gate 		return (ENODEV);
486*7c478bd9Sstevel@tonic-gate 	    }
487*7c478bd9Sstevel@tonic-gate 	} else { /* data_format == FMT_EFI */
488*7c478bd9Sstevel@tonic-gate 	    if (snum < 0 || snum >= efip->efi_nparts ||
489*7c478bd9Sstevel@tonic-gate 		efip->efi_parts[snum].p_size == 0) {
490*7c478bd9Sstevel@tonic-gate 		efi_free(efip);
491*7c478bd9Sstevel@tonic-gate 		return (ENODEV);
492*7c478bd9Sstevel@tonic-gate 	    }
493*7c478bd9Sstevel@tonic-gate 	}
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 	/* the slice exists */
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_INDEX, snum) != 0) {
498*7c478bd9Sstevel@tonic-gate 	    if (data_format == FMT_EFI) {
499*7c478bd9Sstevel@tonic-gate 		efi_free(efip);
500*7c478bd9Sstevel@tonic-gate 	    }
501*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
502*7c478bd9Sstevel@tonic-gate 	}
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate 	if (data_format == FMT_VTOC) {
505*7c478bd9Sstevel@tonic-gate 	    if (nvlist_add_uint64(attrs, DM_START, vtoc.v_part[snum].p_start)
506*7c478bd9Sstevel@tonic-gate 		!= 0) {
507*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
508*7c478bd9Sstevel@tonic-gate 	    }
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 	    if (nvlist_add_uint64(attrs, DM_SIZE, vtoc.v_part[snum].p_size)
511*7c478bd9Sstevel@tonic-gate 		!= 0) {
512*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
513*7c478bd9Sstevel@tonic-gate 	    }
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate 	    if (nvlist_add_uint32(attrs, DM_TAG, vtoc.v_part[snum].p_tag)
516*7c478bd9Sstevel@tonic-gate 		!= 0) {
517*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
518*7c478bd9Sstevel@tonic-gate 	    }
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate 	    if (nvlist_add_uint32(attrs, DM_FLAG, vtoc.v_part[snum].p_flag)
521*7c478bd9Sstevel@tonic-gate 		!= 0) {
522*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
523*7c478bd9Sstevel@tonic-gate 	    }
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 	} else { /* data_format == FMT_EFI */
526*7c478bd9Sstevel@tonic-gate 	    if (nvlist_add_uint64(attrs, DM_START,
527*7c478bd9Sstevel@tonic-gate 		efip->efi_parts[snum].p_start) != 0) {
528*7c478bd9Sstevel@tonic-gate 		efi_free(efip);
529*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
530*7c478bd9Sstevel@tonic-gate 	    }
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	    if (nvlist_add_uint64(attrs, DM_SIZE, efip->efi_parts[snum].p_size)
533*7c478bd9Sstevel@tonic-gate 		!= 0) {
534*7c478bd9Sstevel@tonic-gate 		efi_free(efip);
535*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
536*7c478bd9Sstevel@tonic-gate 	    }
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 	    if (efip->efi_parts[snum].p_name[0] != 0) {
539*7c478bd9Sstevel@tonic-gate 		char	label[EFI_PART_NAME_LEN + 1];
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 		(void) snprintf(label, sizeof (label), "%.*s",
542*7c478bd9Sstevel@tonic-gate 		    EFI_PART_NAME_LEN, efip->efi_parts[snum].p_name);
543*7c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(attrs, DM_EFI_NAME, label) != 0) {
544*7c478bd9Sstevel@tonic-gate 		    efi_free(efip);
545*7c478bd9Sstevel@tonic-gate 		    return (ENOMEM);
546*7c478bd9Sstevel@tonic-gate 		}
547*7c478bd9Sstevel@tonic-gate 	    }
548*7c478bd9Sstevel@tonic-gate 	}
549*7c478bd9Sstevel@tonic-gate 
550*7c478bd9Sstevel@tonic-gate 	if (data_format == FMT_EFI) {
551*7c478bd9Sstevel@tonic-gate 	    efi_free(efip);
552*7c478bd9Sstevel@tonic-gate 	}
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate 	if (inuse_mnt(dp->name, attrs, &error)) {
555*7c478bd9Sstevel@tonic-gate 	    if (error != 0) {
556*7c478bd9Sstevel@tonic-gate 		return (error);
557*7c478bd9Sstevel@tonic-gate 	    }
558*7c478bd9Sstevel@tonic-gate 	    mntpnt = 1;
559*7c478bd9Sstevel@tonic-gate 	}
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate 	/*
562*7c478bd9Sstevel@tonic-gate 	 * Some extra attrs for cluster slices.
563*7c478bd9Sstevel@tonic-gate 	 *
564*7c478bd9Sstevel@tonic-gate 	 * get localname and possible mnt point for localpath
565*7c478bd9Sstevel@tonic-gate 	 */
566*7c478bd9Sstevel@tonic-gate 	localpath[0] = 0;
567*7c478bd9Sstevel@tonic-gate 	diskp = dp->p.disk;
568*7c478bd9Sstevel@tonic-gate 	if (diskp->aliases != NULL && diskp->aliases->cluster) {
569*7c478bd9Sstevel@tonic-gate 	    slice_t *sp;
570*7c478bd9Sstevel@tonic-gate 
571*7c478bd9Sstevel@tonic-gate 	    for (sp = diskp->aliases->orig_paths; sp != NULL; sp = sp->next) {
572*7c478bd9Sstevel@tonic-gate 		if (sp->slice_num == -1) {
573*7c478bd9Sstevel@tonic-gate 		    /* determine the slice number for this path */
574*7c478bd9Sstevel@tonic-gate 		    int			sfd;
575*7c478bd9Sstevel@tonic-gate 		    struct dk_cinfo	dkinfo;
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 		    if ((sfd = open(sp->devpath, O_RDONLY|O_NDELAY)) >= 0) {
578*7c478bd9Sstevel@tonic-gate 			if (ioctl(sfd, DKIOCINFO, &dkinfo) >= 0) {
579*7c478bd9Sstevel@tonic-gate 			    sp->slice_num = dkinfo.dki_partition;
580*7c478bd9Sstevel@tonic-gate 			}
581*7c478bd9Sstevel@tonic-gate 			(void) close(sfd);
582*7c478bd9Sstevel@tonic-gate 		    }
583*7c478bd9Sstevel@tonic-gate 		}
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate 		if (sp->slice_num == snum) {
586*7c478bd9Sstevel@tonic-gate 		    slice_rdsk2dsk(sp->devpath, localpath, sizeof (localpath));
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 		    if (nvlist_add_string(attrs, DM_LOCALNAME, localpath)
589*7c478bd9Sstevel@tonic-gate 			!= 0) {
590*7c478bd9Sstevel@tonic-gate 			return (ENOMEM);
591*7c478bd9Sstevel@tonic-gate 		    }
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 		    if (mntpnt == 0) {
594*7c478bd9Sstevel@tonic-gate 			if (inuse_mnt(localpath, attrs, &error)) {
595*7c478bd9Sstevel@tonic-gate 			    if (error != 0) {
596*7c478bd9Sstevel@tonic-gate 				return (error);
597*7c478bd9Sstevel@tonic-gate 			    }
598*7c478bd9Sstevel@tonic-gate 			}
599*7c478bd9Sstevel@tonic-gate 		    }
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 		    break;
602*7c478bd9Sstevel@tonic-gate 		}
603*7c478bd9Sstevel@tonic-gate 	    }
604*7c478bd9Sstevel@tonic-gate 	}
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 	if (fstat(fd, &buf) != -1) {
607*7c478bd9Sstevel@tonic-gate 	    if (nvlist_add_uint64(attrs, DM_DEVT, buf.st_rdev) != 0) {
608*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
609*7c478bd9Sstevel@tonic-gate 	    }
610*7c478bd9Sstevel@tonic-gate 	}
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate 	/*
613*7c478bd9Sstevel@tonic-gate 	 * We need to open the cooked slice (not the raw one) to get the
614*7c478bd9Sstevel@tonic-gate 	 * correct devid.  Also see if we need to read the localpath for the
615*7c478bd9Sstevel@tonic-gate 	 * cluster disk, since the minor name is unavailable for the did pseudo
616*7c478bd9Sstevel@tonic-gate 	 * device.
617*7c478bd9Sstevel@tonic-gate 	 */
618*7c478bd9Sstevel@tonic-gate 	if (localpath[0] != 0) {
619*7c478bd9Sstevel@tonic-gate 	    cooked_fd = open(localpath, O_RDONLY|O_NDELAY);
620*7c478bd9Sstevel@tonic-gate 	} else {
621*7c478bd9Sstevel@tonic-gate 	    cooked_fd = open(dp->name, O_RDONLY|O_NDELAY);
622*7c478bd9Sstevel@tonic-gate 	}
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	if (cooked_fd >= 0) {
625*7c478bd9Sstevel@tonic-gate 	    int		no_mem = 0;
626*7c478bd9Sstevel@tonic-gate 	    ddi_devid_t	devid;
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate 	    if (devid_get(cooked_fd, &devid) == 0) {
629*7c478bd9Sstevel@tonic-gate 		char	*minor;
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 		if (devid_get_minor_name(cooked_fd, &minor) == 0) {
632*7c478bd9Sstevel@tonic-gate 		    char	*devidstr;
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 		    if ((devidstr = devid_str_encode(devid, minor)) != 0) {
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 			if (nvlist_add_string(attrs, DM_DEVICEID, devidstr)
637*7c478bd9Sstevel@tonic-gate 			    != 0) {
638*7c478bd9Sstevel@tonic-gate 			    no_mem = 1;
639*7c478bd9Sstevel@tonic-gate 			}
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate 			devid_str_free(devidstr);
642*7c478bd9Sstevel@tonic-gate 		    }
643*7c478bd9Sstevel@tonic-gate 		    devid_str_free(minor);
644*7c478bd9Sstevel@tonic-gate 		}
645*7c478bd9Sstevel@tonic-gate 		devid_free(devid);
646*7c478bd9Sstevel@tonic-gate 	    }
647*7c478bd9Sstevel@tonic-gate 	    (void) close(cooked_fd);
648*7c478bd9Sstevel@tonic-gate 
649*7c478bd9Sstevel@tonic-gate 	    if (no_mem) {
650*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
651*7c478bd9Sstevel@tonic-gate 	    }
652*7c478bd9Sstevel@tonic-gate 	}
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate 	return (0);
655*7c478bd9Sstevel@tonic-gate }
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate static descriptor_t **
658*7c478bd9Sstevel@tonic-gate get_fixed_assocs(descriptor_t *desc, int *errp)
659*7c478bd9Sstevel@tonic-gate {
660*7c478bd9Sstevel@tonic-gate 	int		fd;
661*7c478bd9Sstevel@tonic-gate 	int		status;
662*7c478bd9Sstevel@tonic-gate 	int		data_format = FMT_UNKNOWN;
663*7c478bd9Sstevel@tonic-gate 	int		cnt;
664*7c478bd9Sstevel@tonic-gate 	struct vtoc	vtoc;
665*7c478bd9Sstevel@tonic-gate 	struct dk_gpt	*efip;
666*7c478bd9Sstevel@tonic-gate 	int		pos;
667*7c478bd9Sstevel@tonic-gate 	char		*media_name = NULL;
668*7c478bd9Sstevel@tonic-gate 	slice_t		*devp;
669*7c478bd9Sstevel@tonic-gate 	descriptor_t	**slices;
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	if ((fd = drive_open_disk(desc->p.disk, NULL, 0)) < 0) {
672*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
673*7c478bd9Sstevel@tonic-gate 	    return (NULL);
674*7c478bd9Sstevel@tonic-gate 	}
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 	if ((status = read_vtoc(fd, &vtoc)) >= 0) {
677*7c478bd9Sstevel@tonic-gate 	    data_format = FMT_VTOC;
678*7c478bd9Sstevel@tonic-gate 	} else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) {
679*7c478bd9Sstevel@tonic-gate 	    data_format = FMT_EFI;
680*7c478bd9Sstevel@tonic-gate 	} else {
681*7c478bd9Sstevel@tonic-gate 	    (void) close(fd);
682*7c478bd9Sstevel@tonic-gate 	    *errp = 0;
683*7c478bd9Sstevel@tonic-gate 	    return (libdiskmgt_empty_desc_array(errp));
684*7c478bd9Sstevel@tonic-gate 	}
685*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 	/* count the number of slices */
688*7c478bd9Sstevel@tonic-gate 	for (cnt = 0, devp = desc->p.disk->aliases->devpaths; devp != NULL;
689*7c478bd9Sstevel@tonic-gate 	    devp = devp->next, cnt++);
690*7c478bd9Sstevel@tonic-gate 
691*7c478bd9Sstevel@tonic-gate 	/* allocate the array for the descriptors */
692*7c478bd9Sstevel@tonic-gate 	slices = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
693*7c478bd9Sstevel@tonic-gate 	if (slices == NULL) {
694*7c478bd9Sstevel@tonic-gate 	    if (data_format == FMT_EFI) {
695*7c478bd9Sstevel@tonic-gate 		efi_free(efip);
696*7c478bd9Sstevel@tonic-gate 	    }
697*7c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
698*7c478bd9Sstevel@tonic-gate 	    return (NULL);
699*7c478bd9Sstevel@tonic-gate 	}
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate 	/* get the media name from the descriptor */
702*7c478bd9Sstevel@tonic-gate 	if (desc->type == DM_MEDIA) {
703*7c478bd9Sstevel@tonic-gate 	    media_name = desc->name;
704*7c478bd9Sstevel@tonic-gate 	} else {
705*7c478bd9Sstevel@tonic-gate 	    /* must be a DM_PARTITION */
706*7c478bd9Sstevel@tonic-gate 	    media_name = desc->secondary_name;
707*7c478bd9Sstevel@tonic-gate 	}
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate 	pos = 0;
710*7c478bd9Sstevel@tonic-gate 	for (devp = desc->p.disk->aliases->devpaths; devp != NULL;
711*7c478bd9Sstevel@tonic-gate 	    devp = devp->next) {
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	    int		slice_num;
714*7c478bd9Sstevel@tonic-gate 	    char	devpath[MAXPATHLEN];
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 	    slice_num = get_slice_num(devp);
717*7c478bd9Sstevel@tonic-gate 	    /* can't get slicenum, so no need to keep trying the drive */
718*7c478bd9Sstevel@tonic-gate 	    if (slice_num == -1) {
719*7c478bd9Sstevel@tonic-gate 		break;
720*7c478bd9Sstevel@tonic-gate 	    }
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 	    if (data_format == FMT_VTOC) {
723*7c478bd9Sstevel@tonic-gate 		if (slice_num >= vtoc.v_nparts ||
724*7c478bd9Sstevel@tonic-gate 		    vtoc.v_part[slice_num].p_size == 0) {
725*7c478bd9Sstevel@tonic-gate 		    continue;
726*7c478bd9Sstevel@tonic-gate 		}
727*7c478bd9Sstevel@tonic-gate 	    } else { /* data_format == FMT_EFI */
728*7c478bd9Sstevel@tonic-gate 		if (slice_num >= efip->efi_nparts ||
729*7c478bd9Sstevel@tonic-gate 		    efip->efi_parts[slice_num].p_size == 0) {
730*7c478bd9Sstevel@tonic-gate 		    continue;
731*7c478bd9Sstevel@tonic-gate 		}
732*7c478bd9Sstevel@tonic-gate 	    }
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 	    slice_rdsk2dsk(devp->devpath, devpath, sizeof (devpath));
735*7c478bd9Sstevel@tonic-gate 	    slices[pos] = cache_get_desc(DM_SLICE, desc->p.disk, devpath,
736*7c478bd9Sstevel@tonic-gate 		media_name, errp);
737*7c478bd9Sstevel@tonic-gate 	    if (*errp != 0) {
738*7c478bd9Sstevel@tonic-gate 		cache_free_descriptors(slices);
739*7c478bd9Sstevel@tonic-gate 		if (data_format == FMT_EFI) {
740*7c478bd9Sstevel@tonic-gate 		    efi_free(efip);
741*7c478bd9Sstevel@tonic-gate 		}
742*7c478bd9Sstevel@tonic-gate 		return (NULL);
743*7c478bd9Sstevel@tonic-gate 	    }
744*7c478bd9Sstevel@tonic-gate 	    pos++;
745*7c478bd9Sstevel@tonic-gate 	}
746*7c478bd9Sstevel@tonic-gate 	slices[pos] = NULL;
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate 	if (data_format == FMT_EFI) {
749*7c478bd9Sstevel@tonic-gate 	    efi_free(efip);
750*7c478bd9Sstevel@tonic-gate 	}
751*7c478bd9Sstevel@tonic-gate 
752*7c478bd9Sstevel@tonic-gate 	*errp = 0;
753*7c478bd9Sstevel@tonic-gate 	return (slices);
754*7c478bd9Sstevel@tonic-gate }
755*7c478bd9Sstevel@tonic-gate 
756*7c478bd9Sstevel@tonic-gate /*
757*7c478bd9Sstevel@tonic-gate  * Called for loaded removable media under volume management control.
758*7c478bd9Sstevel@tonic-gate  */
759*7c478bd9Sstevel@tonic-gate static descriptor_t **
760*7c478bd9Sstevel@tonic-gate get_removable_assocs(descriptor_t *desc, char *volm_path, int *errp)
761*7c478bd9Sstevel@tonic-gate {
762*7c478bd9Sstevel@tonic-gate 	int		pos;
763*7c478bd9Sstevel@tonic-gate 	int		fd;
764*7c478bd9Sstevel@tonic-gate 	int		cnt;
765*7c478bd9Sstevel@tonic-gate 	struct stat	buf;
766*7c478bd9Sstevel@tonic-gate 	descriptor_t	**slices;
767*7c478bd9Sstevel@tonic-gate 	char		*media_name = NULL;
768*7c478bd9Sstevel@tonic-gate 	char		devpath[MAXPATHLEN];
769*7c478bd9Sstevel@tonic-gate 
770*7c478bd9Sstevel@tonic-gate 	/* get the media name from the descriptor */
771*7c478bd9Sstevel@tonic-gate 	if (desc->type == DM_MEDIA) {
772*7c478bd9Sstevel@tonic-gate 	    media_name = desc->name;
773*7c478bd9Sstevel@tonic-gate 	} else {
774*7c478bd9Sstevel@tonic-gate 	    /* must be a DM_PARTITION */
775*7c478bd9Sstevel@tonic-gate 	    media_name = desc->secondary_name;
776*7c478bd9Sstevel@tonic-gate 	}
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 	/*
779*7c478bd9Sstevel@tonic-gate 	 * For removable media under volm control the volm_path will
780*7c478bd9Sstevel@tonic-gate 	 * either be a device (if the media is made up of a single slice) or
781*7c478bd9Sstevel@tonic-gate 	 * a directory (if the media has multiple slices) with the slices
782*7c478bd9Sstevel@tonic-gate 	 * as devices contained in the directory.
783*7c478bd9Sstevel@tonic-gate 	 */
784*7c478bd9Sstevel@tonic-gate 
785*7c478bd9Sstevel@tonic-gate 	if ((fd = open(volm_path, O_RDONLY|O_NDELAY)) < 0 ||
786*7c478bd9Sstevel@tonic-gate 	    fstat(fd, &buf) != 0) {
787*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
788*7c478bd9Sstevel@tonic-gate 	    return (NULL);
789*7c478bd9Sstevel@tonic-gate 	}
790*7c478bd9Sstevel@tonic-gate 
791*7c478bd9Sstevel@tonic-gate 	cnt = num_removable_slices(fd, &buf, volm_path);
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	/* allocate the array for the descriptors */
794*7c478bd9Sstevel@tonic-gate 	slices = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
795*7c478bd9Sstevel@tonic-gate 	if (slices == NULL) {
796*7c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
797*7c478bd9Sstevel@tonic-gate 	    return (NULL);
798*7c478bd9Sstevel@tonic-gate 	}
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate 	slice_rdsk2dsk(volm_path, devpath, sizeof (devpath));
801*7c478bd9Sstevel@tonic-gate 
802*7c478bd9Sstevel@tonic-gate 	pos = 0;
803*7c478bd9Sstevel@tonic-gate 	*errp = 0;
804*7c478bd9Sstevel@tonic-gate 	if (buf.st_mode & S_IFCHR) {
805*7c478bd9Sstevel@tonic-gate 	    struct dk_minfo	minfo;
806*7c478bd9Sstevel@tonic-gate 
807*7c478bd9Sstevel@tonic-gate 	    /* Make sure media has readable label */
808*7c478bd9Sstevel@tonic-gate 	    if (media_read_info(fd, &minfo)) {
809*7c478bd9Sstevel@tonic-gate 		int		status;
810*7c478bd9Sstevel@tonic-gate 		int		data_format = FMT_UNKNOWN;
811*7c478bd9Sstevel@tonic-gate 		struct vtoc	vtoc;
812*7c478bd9Sstevel@tonic-gate 		struct dk_gpt	*efip;
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 		if ((status = read_vtoc(fd, &vtoc)) >= 0) {
815*7c478bd9Sstevel@tonic-gate 		    data_format = FMT_VTOC;
816*7c478bd9Sstevel@tonic-gate 		} else if (status == VT_ENOTSUP &&
817*7c478bd9Sstevel@tonic-gate 		    efi_alloc_and_read(fd, &efip) >= 0) {
818*7c478bd9Sstevel@tonic-gate 		    data_format = FMT_EFI;
819*7c478bd9Sstevel@tonic-gate 		}
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate 		if (data_format != FMT_UNKNOWN) {
822*7c478bd9Sstevel@tonic-gate 		    /* has a readable label */
823*7c478bd9Sstevel@tonic-gate 		    slices[pos++] = cache_get_desc(DM_SLICE, desc->p.disk,
824*7c478bd9Sstevel@tonic-gate 			devpath, media_name, errp);
825*7c478bd9Sstevel@tonic-gate 		}
826*7c478bd9Sstevel@tonic-gate 	    }
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate 	} else if (buf.st_mode & S_IFDIR) {
829*7c478bd9Sstevel@tonic-gate 	    DIR			*dirp;
830*7c478bd9Sstevel@tonic-gate #ifdef _LP64
831*7c478bd9Sstevel@tonic-gate 	    struct dirent 	*result;
832*7c478bd9Sstevel@tonic-gate #endif
833*7c478bd9Sstevel@tonic-gate 
834*7c478bd9Sstevel@tonic-gate 	    /* rewind, num_removable_slices already traversed */
835*7c478bd9Sstevel@tonic-gate 	    (void) lseek(fd, 0, SEEK_SET);
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate 	    if ((dirp = fdopendir(fd)) != NULL) {
838*7c478bd9Sstevel@tonic-gate 		struct dirent	*dentp;
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 		dentp = (struct dirent *)malloc(sizeof (struct dirent) +
841*7c478bd9Sstevel@tonic-gate 		    _PC_NAME_MAX + 1);
842*7c478bd9Sstevel@tonic-gate 		if (dentp != NULL) {
843*7c478bd9Sstevel@tonic-gate #ifdef _LP64
844*7c478bd9Sstevel@tonic-gate 		    while (readdir_r(dirp, dentp, &result) != NULL) {
845*7c478bd9Sstevel@tonic-gate #else
846*7c478bd9Sstevel@tonic-gate 		    while (readdir_r(dirp, dentp) != NULL) {
847*7c478bd9Sstevel@tonic-gate #endif
848*7c478bd9Sstevel@tonic-gate 			int	dfd;
849*7c478bd9Sstevel@tonic-gate 			int	is_dev = 0;
850*7c478bd9Sstevel@tonic-gate 			char	slice_path[MAXPATHLEN];
851*7c478bd9Sstevel@tonic-gate 
852*7c478bd9Sstevel@tonic-gate 			if (libdiskmgt_str_eq(".", dentp->d_name) ||
853*7c478bd9Sstevel@tonic-gate 			    libdiskmgt_str_eq("..", dentp->d_name)) {
854*7c478bd9Sstevel@tonic-gate 			    continue;
855*7c478bd9Sstevel@tonic-gate 			}
856*7c478bd9Sstevel@tonic-gate 
857*7c478bd9Sstevel@tonic-gate 			(void) snprintf(slice_path, sizeof (slice_path),
858*7c478bd9Sstevel@tonic-gate 			    "%s/%s", devpath, dentp->d_name);
859*7c478bd9Sstevel@tonic-gate 
860*7c478bd9Sstevel@tonic-gate 			if ((dfd = open(slice_path, O_RDONLY|O_NDELAY)) >= 0) {
861*7c478bd9Sstevel@tonic-gate 			    struct stat	buf;
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 			    if (fstat(dfd, &buf) == 0 &&
864*7c478bd9Sstevel@tonic-gate 				buf.st_mode & S_IFCHR) {
865*7c478bd9Sstevel@tonic-gate 				is_dev = 1;
866*7c478bd9Sstevel@tonic-gate 			    }
867*7c478bd9Sstevel@tonic-gate 			    (void) close(dfd);
868*7c478bd9Sstevel@tonic-gate 			}
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 			if (!is_dev) {
871*7c478bd9Sstevel@tonic-gate 			    continue;
872*7c478bd9Sstevel@tonic-gate 			}
873*7c478bd9Sstevel@tonic-gate 
874*7c478bd9Sstevel@tonic-gate 			slices[pos++] = cache_get_desc(DM_SLICE, desc->p.disk,
875*7c478bd9Sstevel@tonic-gate 			    slice_path, media_name, errp);
876*7c478bd9Sstevel@tonic-gate 			if (*errp != 0) {
877*7c478bd9Sstevel@tonic-gate 			    break;
878*7c478bd9Sstevel@tonic-gate 			}
879*7c478bd9Sstevel@tonic-gate 
880*7c478bd9Sstevel@tonic-gate 		    }
881*7c478bd9Sstevel@tonic-gate 		    free(dentp);
882*7c478bd9Sstevel@tonic-gate 		}
883*7c478bd9Sstevel@tonic-gate 		/* don't call closedir since it closes the fd */
884*7c478bd9Sstevel@tonic-gate 	    }
885*7c478bd9Sstevel@tonic-gate 	}
886*7c478bd9Sstevel@tonic-gate 
887*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate 	slices[pos] = NULL;
890*7c478bd9Sstevel@tonic-gate 
891*7c478bd9Sstevel@tonic-gate 	if (*errp != 0) {
892*7c478bd9Sstevel@tonic-gate 	    cache_free_descriptors(slices);
893*7c478bd9Sstevel@tonic-gate 	    return (NULL);
894*7c478bd9Sstevel@tonic-gate 	}
895*7c478bd9Sstevel@tonic-gate 
896*7c478bd9Sstevel@tonic-gate 	return (slices);
897*7c478bd9Sstevel@tonic-gate }
898*7c478bd9Sstevel@tonic-gate 
899*7c478bd9Sstevel@tonic-gate static int
900*7c478bd9Sstevel@tonic-gate get_slice_num(slice_t *devp)
901*7c478bd9Sstevel@tonic-gate {
902*7c478bd9Sstevel@tonic-gate 	/* check if we already determined the devpath slice number */
903*7c478bd9Sstevel@tonic-gate 	if (devp->slice_num == -1) {
904*7c478bd9Sstevel@tonic-gate 	    int		fd;
905*7c478bd9Sstevel@tonic-gate 
906*7c478bd9Sstevel@tonic-gate 	    if ((fd = open(devp->devpath, O_RDONLY|O_NDELAY)) >= 0) {
907*7c478bd9Sstevel@tonic-gate 		struct dk_cinfo	dkinfo;
908*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, DKIOCINFO, &dkinfo) >= 0) {
909*7c478bd9Sstevel@tonic-gate 		    devp->slice_num = dkinfo.dki_partition;
910*7c478bd9Sstevel@tonic-gate 		}
911*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
912*7c478bd9Sstevel@tonic-gate 	    }
913*7c478bd9Sstevel@tonic-gate 	}
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate 	return (devp->slice_num);
916*7c478bd9Sstevel@tonic-gate }
917*7c478bd9Sstevel@tonic-gate 
918*7c478bd9Sstevel@tonic-gate static int
919*7c478bd9Sstevel@tonic-gate make_fixed_descriptors(disk_t *dp)
920*7c478bd9Sstevel@tonic-gate {
921*7c478bd9Sstevel@tonic-gate 	int		error = 0;
922*7c478bd9Sstevel@tonic-gate 	alias_t		*ap;
923*7c478bd9Sstevel@tonic-gate 	slice_t		*devp;
924*7c478bd9Sstevel@tonic-gate 	char		mname[MAXPATHLEN];
925*7c478bd9Sstevel@tonic-gate 	int		data_format = FMT_UNKNOWN;
926*7c478bd9Sstevel@tonic-gate 	struct vtoc	vtoc;
927*7c478bd9Sstevel@tonic-gate 	struct dk_gpt	*efip;
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 	/* Just check the first drive name. */
930*7c478bd9Sstevel@tonic-gate 	if ((ap = dp->aliases) == NULL) {
931*7c478bd9Sstevel@tonic-gate 	    return (0);
932*7c478bd9Sstevel@tonic-gate 	}
933*7c478bd9Sstevel@tonic-gate 
934*7c478bd9Sstevel@tonic-gate 	mname[0] = 0;
935*7c478bd9Sstevel@tonic-gate 	(void) media_read_name(dp, mname, sizeof (mname));
936*7c478bd9Sstevel@tonic-gate 
937*7c478bd9Sstevel@tonic-gate 	for (devp = ap->devpaths; devp != NULL; devp = devp->next) {
938*7c478bd9Sstevel@tonic-gate 	    int		slice_num;
939*7c478bd9Sstevel@tonic-gate 	    char	devpath[MAXPATHLEN];
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate 	    slice_num = get_slice_num(devp);
942*7c478bd9Sstevel@tonic-gate 	    /* can't get slicenum, so no need to keep trying the drive */
943*7c478bd9Sstevel@tonic-gate 	    if (slice_num == -1) {
944*7c478bd9Sstevel@tonic-gate 		break;
945*7c478bd9Sstevel@tonic-gate 	    }
946*7c478bd9Sstevel@tonic-gate 
947*7c478bd9Sstevel@tonic-gate 	    if (data_format == FMT_UNKNOWN) {
948*7c478bd9Sstevel@tonic-gate 		int	fd;
949*7c478bd9Sstevel@tonic-gate 		int	status;
950*7c478bd9Sstevel@tonic-gate 
951*7c478bd9Sstevel@tonic-gate 		if ((fd = drive_open_disk(dp, NULL, 0)) >= 0) {
952*7c478bd9Sstevel@tonic-gate 		    if ((status = read_vtoc(fd, &vtoc)) >= 0) {
953*7c478bd9Sstevel@tonic-gate 			data_format = FMT_VTOC;
954*7c478bd9Sstevel@tonic-gate 		    } else if (status == VT_ENOTSUP &&
955*7c478bd9Sstevel@tonic-gate 			efi_alloc_and_read(fd, &efip) >= 0) {
956*7c478bd9Sstevel@tonic-gate 			data_format = FMT_EFI;
957*7c478bd9Sstevel@tonic-gate 		    }
958*7c478bd9Sstevel@tonic-gate 		    (void) close(fd);
959*7c478bd9Sstevel@tonic-gate 		}
960*7c478bd9Sstevel@tonic-gate 	    }
961*7c478bd9Sstevel@tonic-gate 
962*7c478bd9Sstevel@tonic-gate 	    /* can't get slice data, so no need to keep trying the drive */
963*7c478bd9Sstevel@tonic-gate 	    if (data_format == FMT_UNKNOWN) {
964*7c478bd9Sstevel@tonic-gate 		break;
965*7c478bd9Sstevel@tonic-gate 	    }
966*7c478bd9Sstevel@tonic-gate 
967*7c478bd9Sstevel@tonic-gate 	    if (data_format == FMT_VTOC) {
968*7c478bd9Sstevel@tonic-gate 		if (slice_num >= vtoc.v_nparts ||
969*7c478bd9Sstevel@tonic-gate 		    vtoc.v_part[slice_num].p_size == 0) {
970*7c478bd9Sstevel@tonic-gate 		    continue;
971*7c478bd9Sstevel@tonic-gate 		}
972*7c478bd9Sstevel@tonic-gate 	    } else { /* data_format == FMT_EFI */
973*7c478bd9Sstevel@tonic-gate 		if (slice_num >= efip->efi_nparts ||
974*7c478bd9Sstevel@tonic-gate 		    efip->efi_parts[slice_num].p_size == 0) {
975*7c478bd9Sstevel@tonic-gate 		    continue;
976*7c478bd9Sstevel@tonic-gate 		}
977*7c478bd9Sstevel@tonic-gate 	    }
978*7c478bd9Sstevel@tonic-gate 
979*7c478bd9Sstevel@tonic-gate 	    slice_rdsk2dsk(devp->devpath, devpath, sizeof (devpath));
980*7c478bd9Sstevel@tonic-gate 	    cache_load_desc(DM_SLICE, dp, devpath, mname, &error);
981*7c478bd9Sstevel@tonic-gate 	    if (error != 0) {
982*7c478bd9Sstevel@tonic-gate 		break;
983*7c478bd9Sstevel@tonic-gate 	    }
984*7c478bd9Sstevel@tonic-gate 	}
985*7c478bd9Sstevel@tonic-gate 
986*7c478bd9Sstevel@tonic-gate 	if (data_format == FMT_EFI) {
987*7c478bd9Sstevel@tonic-gate 	    efi_free(efip);
988*7c478bd9Sstevel@tonic-gate 	}
989*7c478bd9Sstevel@tonic-gate 
990*7c478bd9Sstevel@tonic-gate 	return (error);
991*7c478bd9Sstevel@tonic-gate }
992*7c478bd9Sstevel@tonic-gate 
993*7c478bd9Sstevel@tonic-gate /*
994*7c478bd9Sstevel@tonic-gate  * For removable media under volm control we have to do some special handling.
995*7c478bd9Sstevel@tonic-gate  * We don't use the vtoc and /dev/dsk devpaths, since the slices are named
996*7c478bd9Sstevel@tonic-gate  * under the /vol fs.
997*7c478bd9Sstevel@tonic-gate  */
998*7c478bd9Sstevel@tonic-gate static int
999*7c478bd9Sstevel@tonic-gate make_removable_descriptors(disk_t *dp)
1000*7c478bd9Sstevel@tonic-gate {
1001*7c478bd9Sstevel@tonic-gate 	char		volm_path[MAXPATHLEN];
1002*7c478bd9Sstevel@tonic-gate 	int		error;
1003*7c478bd9Sstevel@tonic-gate 	int		fd;
1004*7c478bd9Sstevel@tonic-gate 
1005*7c478bd9Sstevel@tonic-gate 	/*
1006*7c478bd9Sstevel@tonic-gate 	 * If this removable drive is not under volm control, just use
1007*7c478bd9Sstevel@tonic-gate 	 * normal handling.
1008*7c478bd9Sstevel@tonic-gate 	 */
1009*7c478bd9Sstevel@tonic-gate 	if (!media_get_volm_path(dp, volm_path, sizeof (volm_path))) {
1010*7c478bd9Sstevel@tonic-gate 	    return (make_fixed_descriptors(dp));
1011*7c478bd9Sstevel@tonic-gate 	}
1012*7c478bd9Sstevel@tonic-gate 
1013*7c478bd9Sstevel@tonic-gate 	if (volm_path[0] == 0) {
1014*7c478bd9Sstevel@tonic-gate 	    /* no media */
1015*7c478bd9Sstevel@tonic-gate 	    return (0);
1016*7c478bd9Sstevel@tonic-gate 	}
1017*7c478bd9Sstevel@tonic-gate 
1018*7c478bd9Sstevel@tonic-gate 	/*
1019*7c478bd9Sstevel@tonic-gate 	 * For removable media under volm control the rmmedia_devapth will
1020*7c478bd9Sstevel@tonic-gate 	 * either be a device (if the media is made up of a single slice) or
1021*7c478bd9Sstevel@tonic-gate 	 * a directory (if the media has multiple slices) with the slices
1022*7c478bd9Sstevel@tonic-gate 	 * as devices contained in the directory.
1023*7c478bd9Sstevel@tonic-gate 	 */
1024*7c478bd9Sstevel@tonic-gate 	error = 0;
1025*7c478bd9Sstevel@tonic-gate 	if ((fd = open(volm_path, O_RDONLY|O_NDELAY)) >= 0) {
1026*7c478bd9Sstevel@tonic-gate 	    struct stat	buf;
1027*7c478bd9Sstevel@tonic-gate 
1028*7c478bd9Sstevel@tonic-gate 	    if (fstat(fd, &buf) == 0) {
1029*7c478bd9Sstevel@tonic-gate 		if (buf.st_mode & S_IFCHR) {
1030*7c478bd9Sstevel@tonic-gate 		    int			status;
1031*7c478bd9Sstevel@tonic-gate 		    int			data_format = FMT_UNKNOWN;
1032*7c478bd9Sstevel@tonic-gate 		    struct dk_minfo	minfo;
1033*7c478bd9Sstevel@tonic-gate 		    int			error;
1034*7c478bd9Sstevel@tonic-gate 		    struct vtoc		vtoc;
1035*7c478bd9Sstevel@tonic-gate 		    struct dk_gpt	*efip;
1036*7c478bd9Sstevel@tonic-gate 		    char		devpath[MAXPATHLEN];
1037*7c478bd9Sstevel@tonic-gate 
1038*7c478bd9Sstevel@tonic-gate 		    /* Make sure media has readable label */
1039*7c478bd9Sstevel@tonic-gate 		    if (!media_read_info(fd, &minfo)) {
1040*7c478bd9Sstevel@tonic-gate 			/* no media */
1041*7c478bd9Sstevel@tonic-gate 			return (0);
1042*7c478bd9Sstevel@tonic-gate 		    }
1043*7c478bd9Sstevel@tonic-gate 
1044*7c478bd9Sstevel@tonic-gate 		    if ((status = read_vtoc(fd, &vtoc)) >= 0) {
1045*7c478bd9Sstevel@tonic-gate 			data_format = FMT_VTOC;
1046*7c478bd9Sstevel@tonic-gate 		    } else if (status == VT_ENOTSUP &&
1047*7c478bd9Sstevel@tonic-gate 			efi_alloc_and_read(fd, &efip) >= 0) {
1048*7c478bd9Sstevel@tonic-gate 			data_format = FMT_EFI;
1049*7c478bd9Sstevel@tonic-gate 		    }
1050*7c478bd9Sstevel@tonic-gate 
1051*7c478bd9Sstevel@tonic-gate 		    if (data_format == FMT_UNKNOWN) {
1052*7c478bd9Sstevel@tonic-gate 			/* no readable label */
1053*7c478bd9Sstevel@tonic-gate 			return (0);
1054*7c478bd9Sstevel@tonic-gate 		    }
1055*7c478bd9Sstevel@tonic-gate 
1056*7c478bd9Sstevel@tonic-gate 		    slice_rdsk2dsk(volm_path, devpath, sizeof (devpath));
1057*7c478bd9Sstevel@tonic-gate 		    /* The media name is the volm_path in this case. */
1058*7c478bd9Sstevel@tonic-gate 		    cache_load_desc(DM_SLICE, dp, devpath, volm_path, &error);
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 		} else if (buf.st_mode & S_IFDIR) {
1061*7c478bd9Sstevel@tonic-gate 		    /* each device file in the dir represents a slice */
1062*7c478bd9Sstevel@tonic-gate 		    error = make_volm_dir_descriptors(dp, fd, volm_path);
1063*7c478bd9Sstevel@tonic-gate 		}
1064*7c478bd9Sstevel@tonic-gate 	    }
1065*7c478bd9Sstevel@tonic-gate 	    (void) close(fd);
1066*7c478bd9Sstevel@tonic-gate 	}
1067*7c478bd9Sstevel@tonic-gate 
1068*7c478bd9Sstevel@tonic-gate 	return (error);
1069*7c478bd9Sstevel@tonic-gate }
1070*7c478bd9Sstevel@tonic-gate 
1071*7c478bd9Sstevel@tonic-gate /*
1072*7c478bd9Sstevel@tonic-gate  * This handles removable media with slices under volume management control.
1073*7c478bd9Sstevel@tonic-gate  * In this case we have a dir which is the media name and each slice on the
1074*7c478bd9Sstevel@tonic-gate  * media is a device file in this dir.
1075*7c478bd9Sstevel@tonic-gate  */
1076*7c478bd9Sstevel@tonic-gate static int
1077*7c478bd9Sstevel@tonic-gate make_volm_dir_descriptors(disk_t *dp, int dirfd, char *volm_path)
1078*7c478bd9Sstevel@tonic-gate {
1079*7c478bd9Sstevel@tonic-gate 	int		error;
1080*7c478bd9Sstevel@tonic-gate 	DIR		*dirp;
1081*7c478bd9Sstevel@tonic-gate 	struct dirent	*dentp;
1082*7c478bd9Sstevel@tonic-gate #ifdef _LP64
1083*7c478bd9Sstevel@tonic-gate 	struct dirent	*result;
1084*7c478bd9Sstevel@tonic-gate #endif
1085*7c478bd9Sstevel@tonic-gate 	char		devpath[MAXPATHLEN];
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate 	if ((dirp = fdopendir(dirfd)) == NULL) {
1088*7c478bd9Sstevel@tonic-gate 	    return (0);
1089*7c478bd9Sstevel@tonic-gate 	}
1090*7c478bd9Sstevel@tonic-gate 
1091*7c478bd9Sstevel@tonic-gate 	slice_rdsk2dsk(volm_path, devpath, sizeof (devpath));
1092*7c478bd9Sstevel@tonic-gate 
1093*7c478bd9Sstevel@tonic-gate 	error = 0;
1094*7c478bd9Sstevel@tonic-gate 	dentp = (struct dirent *)malloc(sizeof (struct dirent) +
1095*7c478bd9Sstevel@tonic-gate 	    _PC_NAME_MAX + 1);
1096*7c478bd9Sstevel@tonic-gate 	if (dentp != NULL) {
1097*7c478bd9Sstevel@tonic-gate #ifdef _LP64
1098*7c478bd9Sstevel@tonic-gate 	    while (readdir_r(dirp, dentp, &result) != NULL) {
1099*7c478bd9Sstevel@tonic-gate #else
1100*7c478bd9Sstevel@tonic-gate 	    while (readdir_r(dirp, dentp) != NULL) {
1101*7c478bd9Sstevel@tonic-gate #endif
1102*7c478bd9Sstevel@tonic-gate 		int	fd;
1103*7c478bd9Sstevel@tonic-gate 		char	slice_path[MAXPATHLEN];
1104*7c478bd9Sstevel@tonic-gate 
1105*7c478bd9Sstevel@tonic-gate 		if (libdiskmgt_str_eq(".", dentp->d_name) ||
1106*7c478bd9Sstevel@tonic-gate 		    libdiskmgt_str_eq("..", dentp->d_name)) {
1107*7c478bd9Sstevel@tonic-gate 		    continue;
1108*7c478bd9Sstevel@tonic-gate 		}
1109*7c478bd9Sstevel@tonic-gate 
1110*7c478bd9Sstevel@tonic-gate 		(void) snprintf(slice_path, sizeof (slice_path), "%s/%s",
1111*7c478bd9Sstevel@tonic-gate 		    devpath, dentp->d_name);
1112*7c478bd9Sstevel@tonic-gate 
1113*7c478bd9Sstevel@tonic-gate 		if ((fd = open(slice_path, O_RDONLY|O_NDELAY)) >= 0) {
1114*7c478bd9Sstevel@tonic-gate 		    struct stat	buf;
1115*7c478bd9Sstevel@tonic-gate 
1116*7c478bd9Sstevel@tonic-gate 		    if (fstat(fd, &buf) == 0 && buf.st_mode & S_IFCHR) {
1117*7c478bd9Sstevel@tonic-gate 			/* The media name is the volm_path in this case. */
1118*7c478bd9Sstevel@tonic-gate 			cache_load_desc(DM_SLICE, dp, slice_path, volm_path,
1119*7c478bd9Sstevel@tonic-gate 			    &error);
1120*7c478bd9Sstevel@tonic-gate 			if (error != 0) {
1121*7c478bd9Sstevel@tonic-gate 			    (void) close(fd);
1122*7c478bd9Sstevel@tonic-gate 			    break;
1123*7c478bd9Sstevel@tonic-gate 			}
1124*7c478bd9Sstevel@tonic-gate 		    }
1125*7c478bd9Sstevel@tonic-gate 
1126*7c478bd9Sstevel@tonic-gate 		    (void) close(fd);
1127*7c478bd9Sstevel@tonic-gate 		}
1128*7c478bd9Sstevel@tonic-gate 	    }
1129*7c478bd9Sstevel@tonic-gate 	    free(dentp);
1130*7c478bd9Sstevel@tonic-gate 	}
1131*7c478bd9Sstevel@tonic-gate 	/* don't call closedir since it closes the fd */
1132*7c478bd9Sstevel@tonic-gate 
1133*7c478bd9Sstevel@tonic-gate 	return (error);
1134*7c478bd9Sstevel@tonic-gate }
1135*7c478bd9Sstevel@tonic-gate 
1136*7c478bd9Sstevel@tonic-gate /*
1137*7c478bd9Sstevel@tonic-gate  * Just look for the name on the devpaths we have cached. Return 1 if we
1138*7c478bd9Sstevel@tonic-gate  * find the name and the size of that slice is non-zero.
1139*7c478bd9Sstevel@tonic-gate  */
1140*7c478bd9Sstevel@tonic-gate static int
1141*7c478bd9Sstevel@tonic-gate match_fixed_name(disk_t *diskp, char *name, int *errp)
1142*7c478bd9Sstevel@tonic-gate {
1143*7c478bd9Sstevel@tonic-gate 	slice_t		*dp = NULL;
1144*7c478bd9Sstevel@tonic-gate 	alias_t		*ap;
1145*7c478bd9Sstevel@tonic-gate 	int		slice_num;
1146*7c478bd9Sstevel@tonic-gate 	int		fd;
1147*7c478bd9Sstevel@tonic-gate 	int		status;
1148*7c478bd9Sstevel@tonic-gate 	int		data_format = FMT_UNKNOWN;
1149*7c478bd9Sstevel@tonic-gate 	struct vtoc	vtoc;
1150*7c478bd9Sstevel@tonic-gate 	struct dk_gpt	*efip;
1151*7c478bd9Sstevel@tonic-gate 
1152*7c478bd9Sstevel@tonic-gate 	ap = diskp->aliases;
1153*7c478bd9Sstevel@tonic-gate 	while (ap != NULL) {
1154*7c478bd9Sstevel@tonic-gate 	    slice_t	*devp;
1155*7c478bd9Sstevel@tonic-gate 
1156*7c478bd9Sstevel@tonic-gate 	    devp = ap->devpaths;
1157*7c478bd9Sstevel@tonic-gate 	    while (devp != NULL) {
1158*7c478bd9Sstevel@tonic-gate 		char	path[MAXPATHLEN];
1159*7c478bd9Sstevel@tonic-gate 
1160*7c478bd9Sstevel@tonic-gate 		slice_rdsk2dsk(devp->devpath, path, sizeof (path));
1161*7c478bd9Sstevel@tonic-gate 		if (libdiskmgt_str_eq(path, name)) {
1162*7c478bd9Sstevel@tonic-gate 		    /* found it */
1163*7c478bd9Sstevel@tonic-gate 		    dp = devp;
1164*7c478bd9Sstevel@tonic-gate 		    break;
1165*7c478bd9Sstevel@tonic-gate 		}
1166*7c478bd9Sstevel@tonic-gate 
1167*7c478bd9Sstevel@tonic-gate 		devp = devp->next;
1168*7c478bd9Sstevel@tonic-gate 	    }
1169*7c478bd9Sstevel@tonic-gate 
1170*7c478bd9Sstevel@tonic-gate 	    if (dp != NULL) {
1171*7c478bd9Sstevel@tonic-gate 		break;
1172*7c478bd9Sstevel@tonic-gate 	    }
1173*7c478bd9Sstevel@tonic-gate 
1174*7c478bd9Sstevel@tonic-gate 	    ap = ap->next;
1175*7c478bd9Sstevel@tonic-gate 	}
1176*7c478bd9Sstevel@tonic-gate 
1177*7c478bd9Sstevel@tonic-gate 	if (dp == NULL) {
1178*7c478bd9Sstevel@tonic-gate 	    *errp = 0;
1179*7c478bd9Sstevel@tonic-gate 	    return (0);
1180*7c478bd9Sstevel@tonic-gate 	}
1181*7c478bd9Sstevel@tonic-gate 
1182*7c478bd9Sstevel@tonic-gate 	/*
1183*7c478bd9Sstevel@tonic-gate 	 * If we found a match on the name we now have to check that this
1184*7c478bd9Sstevel@tonic-gate 	 * slice really exists (non-0 size).
1185*7c478bd9Sstevel@tonic-gate 	 */
1186*7c478bd9Sstevel@tonic-gate 
1187*7c478bd9Sstevel@tonic-gate 	slice_num = get_slice_num(dp);
1188*7c478bd9Sstevel@tonic-gate 	/* can't get slicenum, so no slice */
1189*7c478bd9Sstevel@tonic-gate 	if (slice_num == -1) {
1190*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
1191*7c478bd9Sstevel@tonic-gate 	    return (1);
1192*7c478bd9Sstevel@tonic-gate 	}
1193*7c478bd9Sstevel@tonic-gate 
1194*7c478bd9Sstevel@tonic-gate 	if ((fd = drive_open_disk(diskp, NULL, 0)) < 0) {
1195*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
1196*7c478bd9Sstevel@tonic-gate 	    return (1);
1197*7c478bd9Sstevel@tonic-gate 	}
1198*7c478bd9Sstevel@tonic-gate 
1199*7c478bd9Sstevel@tonic-gate 	if ((status = read_vtoc(fd, &vtoc)) >= 0) {
1200*7c478bd9Sstevel@tonic-gate 	    data_format = FMT_VTOC;
1201*7c478bd9Sstevel@tonic-gate 	} else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) {
1202*7c478bd9Sstevel@tonic-gate 	    data_format = FMT_EFI;
1203*7c478bd9Sstevel@tonic-gate 	} else {
1204*7c478bd9Sstevel@tonic-gate 	    (void) close(fd);
1205*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
1206*7c478bd9Sstevel@tonic-gate 	    return (1);
1207*7c478bd9Sstevel@tonic-gate 	}
1208*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
1209*7c478bd9Sstevel@tonic-gate 
1210*7c478bd9Sstevel@tonic-gate 	if (data_format == FMT_VTOC) {
1211*7c478bd9Sstevel@tonic-gate 	    if (slice_num < vtoc.v_nparts &&
1212*7c478bd9Sstevel@tonic-gate 		vtoc.v_part[slice_num].p_size > 0) {
1213*7c478bd9Sstevel@tonic-gate 		*errp = 0;
1214*7c478bd9Sstevel@tonic-gate 		return (1);
1215*7c478bd9Sstevel@tonic-gate 	    }
1216*7c478bd9Sstevel@tonic-gate 	} else { /* data_format == FMT_EFI */
1217*7c478bd9Sstevel@tonic-gate 	    if (slice_num < efip->efi_nparts &&
1218*7c478bd9Sstevel@tonic-gate 		efip->efi_parts[slice_num].p_size > 0) {
1219*7c478bd9Sstevel@tonic-gate 		efi_free(efip);
1220*7c478bd9Sstevel@tonic-gate 		*errp = 0;
1221*7c478bd9Sstevel@tonic-gate 		return (1);
1222*7c478bd9Sstevel@tonic-gate 	    }
1223*7c478bd9Sstevel@tonic-gate 	    efi_free(efip);
1224*7c478bd9Sstevel@tonic-gate 	}
1225*7c478bd9Sstevel@tonic-gate 
1226*7c478bd9Sstevel@tonic-gate 	*errp = ENODEV;
1227*7c478bd9Sstevel@tonic-gate 	return (1);
1228*7c478bd9Sstevel@tonic-gate }
1229*7c478bd9Sstevel@tonic-gate 
1230*7c478bd9Sstevel@tonic-gate static int
1231*7c478bd9Sstevel@tonic-gate match_removable_name(disk_t *diskp, char *name, int *errp)
1232*7c478bd9Sstevel@tonic-gate {
1233*7c478bd9Sstevel@tonic-gate 	char		volm_path[MAXPATHLEN];
1234*7c478bd9Sstevel@tonic-gate 	int		found;
1235*7c478bd9Sstevel@tonic-gate 	int		fd;
1236*7c478bd9Sstevel@tonic-gate 	struct stat	buf;
1237*7c478bd9Sstevel@tonic-gate 
1238*7c478bd9Sstevel@tonic-gate 	/*
1239*7c478bd9Sstevel@tonic-gate 	 * If this removable drive is not under volm control, just use
1240*7c478bd9Sstevel@tonic-gate 	 * normal handling.
1241*7c478bd9Sstevel@tonic-gate 	 */
1242*7c478bd9Sstevel@tonic-gate 	if (!media_get_volm_path(diskp, volm_path, sizeof (volm_path))) {
1243*7c478bd9Sstevel@tonic-gate 	    return (match_fixed_name(diskp, name, errp));
1244*7c478bd9Sstevel@tonic-gate 	}
1245*7c478bd9Sstevel@tonic-gate 
1246*7c478bd9Sstevel@tonic-gate 	if (volm_path[0] == 0) {
1247*7c478bd9Sstevel@tonic-gate 	    /* no media */
1248*7c478bd9Sstevel@tonic-gate 	    *errp = 0;
1249*7c478bd9Sstevel@tonic-gate 	    return (0);
1250*7c478bd9Sstevel@tonic-gate 	}
1251*7c478bd9Sstevel@tonic-gate 
1252*7c478bd9Sstevel@tonic-gate 	/*
1253*7c478bd9Sstevel@tonic-gate 	 * For removable media under volm control the rmmedia_devapth will
1254*7c478bd9Sstevel@tonic-gate 	 * either be a device (if the media is made up of a single slice) or
1255*7c478bd9Sstevel@tonic-gate 	 * a directory (if the media has multiple slices) with the slices
1256*7c478bd9Sstevel@tonic-gate 	 * as devices contained in the directory.
1257*7c478bd9Sstevel@tonic-gate 	 */
1258*7c478bd9Sstevel@tonic-gate 
1259*7c478bd9Sstevel@tonic-gate 	*errp = 0;
1260*7c478bd9Sstevel@tonic-gate 
1261*7c478bd9Sstevel@tonic-gate 	found = 0;
1262*7c478bd9Sstevel@tonic-gate 	if ((fd = open(volm_path, O_RDONLY|O_NDELAY)) >= 0 &&
1263*7c478bd9Sstevel@tonic-gate 	    fstat(fd, &buf) == 0) {
1264*7c478bd9Sstevel@tonic-gate 
1265*7c478bd9Sstevel@tonic-gate 	    if (buf.st_mode & S_IFCHR) {
1266*7c478bd9Sstevel@tonic-gate 		char	devpath[MAXPATHLEN];
1267*7c478bd9Sstevel@tonic-gate 
1268*7c478bd9Sstevel@tonic-gate 		slice_rdsk2dsk(volm_path, devpath, sizeof (devpath));
1269*7c478bd9Sstevel@tonic-gate 		if (libdiskmgt_str_eq(name, devpath)) {
1270*7c478bd9Sstevel@tonic-gate 		    found = 1;
1271*7c478bd9Sstevel@tonic-gate 		}
1272*7c478bd9Sstevel@tonic-gate 
1273*7c478bd9Sstevel@tonic-gate 	    } else if (buf.st_mode & S_IFDIR) {
1274*7c478bd9Sstevel@tonic-gate 		/* each device file in the dir represents a slice */
1275*7c478bd9Sstevel@tonic-gate 		DIR		*dirp;
1276*7c478bd9Sstevel@tonic-gate 
1277*7c478bd9Sstevel@tonic-gate 		if ((dirp = fdopendir(fd)) != NULL) {
1278*7c478bd9Sstevel@tonic-gate 		    struct dirent	*dentp;
1279*7c478bd9Sstevel@tonic-gate #ifdef _LP64
1280*7c478bd9Sstevel@tonic-gate 		    struct dirent	*result;
1281*7c478bd9Sstevel@tonic-gate #endif
1282*7c478bd9Sstevel@tonic-gate 		    char		devpath[MAXPATHLEN];
1283*7c478bd9Sstevel@tonic-gate 
1284*7c478bd9Sstevel@tonic-gate 		    slice_rdsk2dsk(volm_path, devpath, sizeof (devpath));
1285*7c478bd9Sstevel@tonic-gate 
1286*7c478bd9Sstevel@tonic-gate 		    dentp = (struct dirent *)malloc(sizeof (struct dirent) +
1287*7c478bd9Sstevel@tonic-gate 			_PC_NAME_MAX + 1);
1288*7c478bd9Sstevel@tonic-gate 		    if (dentp != NULL) {
1289*7c478bd9Sstevel@tonic-gate #ifdef _LP64
1290*7c478bd9Sstevel@tonic-gate 			while (readdir_r(dirp, dentp, &result) != NULL) {
1291*7c478bd9Sstevel@tonic-gate #else
1292*7c478bd9Sstevel@tonic-gate 			while (readdir_r(dirp, dentp) != NULL) {
1293*7c478bd9Sstevel@tonic-gate #endif
1294*7c478bd9Sstevel@tonic-gate 			    char	slice_path[MAXPATHLEN];
1295*7c478bd9Sstevel@tonic-gate 
1296*7c478bd9Sstevel@tonic-gate 			    if (libdiskmgt_str_eq(".", dentp->d_name) ||
1297*7c478bd9Sstevel@tonic-gate 				libdiskmgt_str_eq("..", dentp->d_name)) {
1298*7c478bd9Sstevel@tonic-gate 				continue;
1299*7c478bd9Sstevel@tonic-gate 			    }
1300*7c478bd9Sstevel@tonic-gate 
1301*7c478bd9Sstevel@tonic-gate 			    (void) snprintf(slice_path, sizeof (slice_path),
1302*7c478bd9Sstevel@tonic-gate 				"%s/%s", devpath, dentp->d_name);
1303*7c478bd9Sstevel@tonic-gate 
1304*7c478bd9Sstevel@tonic-gate 			    if (libdiskmgt_str_eq(name, slice_path)) {
1305*7c478bd9Sstevel@tonic-gate 				/* found name, check device */
1306*7c478bd9Sstevel@tonic-gate 				int	dfd;
1307*7c478bd9Sstevel@tonic-gate 				int	is_dev = 0;
1308*7c478bd9Sstevel@tonic-gate 
1309*7c478bd9Sstevel@tonic-gate 				if ((dfd = open(slice_path, O_RDONLY|O_NDELAY))
1310*7c478bd9Sstevel@tonic-gate 				    >= 0) {
1311*7c478bd9Sstevel@tonic-gate 				    struct stat	buf;
1312*7c478bd9Sstevel@tonic-gate 
1313*7c478bd9Sstevel@tonic-gate 				    if (fstat(dfd, &buf) == 0 &&
1314*7c478bd9Sstevel@tonic-gate 					buf.st_mode & S_IFCHR) {
1315*7c478bd9Sstevel@tonic-gate 					is_dev = 1;
1316*7c478bd9Sstevel@tonic-gate 				    }
1317*7c478bd9Sstevel@tonic-gate 				    (void) close(dfd);
1318*7c478bd9Sstevel@tonic-gate 				}
1319*7c478bd9Sstevel@tonic-gate 
1320*7c478bd9Sstevel@tonic-gate 				/* we found the name */
1321*7c478bd9Sstevel@tonic-gate 				found = 1;
1322*7c478bd9Sstevel@tonic-gate 
1323*7c478bd9Sstevel@tonic-gate 				if (!is_dev) {
1324*7c478bd9Sstevel@tonic-gate 				    *errp = ENODEV;
1325*7c478bd9Sstevel@tonic-gate 				}
1326*7c478bd9Sstevel@tonic-gate 
1327*7c478bd9Sstevel@tonic-gate 				break;
1328*7c478bd9Sstevel@tonic-gate 			    }
1329*7c478bd9Sstevel@tonic-gate 			}
1330*7c478bd9Sstevel@tonic-gate 			free(dentp);
1331*7c478bd9Sstevel@tonic-gate 		    }
1332*7c478bd9Sstevel@tonic-gate 		    /* don't call closedir since it closes the fd */
1333*7c478bd9Sstevel@tonic-gate 		}
1334*7c478bd9Sstevel@tonic-gate 	    } /* end of dir handling */
1335*7c478bd9Sstevel@tonic-gate 
1336*7c478bd9Sstevel@tonic-gate 	    (void) close(fd);
1337*7c478bd9Sstevel@tonic-gate 	}
1338*7c478bd9Sstevel@tonic-gate 
1339*7c478bd9Sstevel@tonic-gate 	return (found);
1340*7c478bd9Sstevel@tonic-gate }
1341*7c478bd9Sstevel@tonic-gate 
1342*7c478bd9Sstevel@tonic-gate static int
1343*7c478bd9Sstevel@tonic-gate num_removable_slices(int fd, struct stat *bufp, char *volm_path)
1344*7c478bd9Sstevel@tonic-gate {
1345*7c478bd9Sstevel@tonic-gate 	int cnt = 0;
1346*7c478bd9Sstevel@tonic-gate 
1347*7c478bd9Sstevel@tonic-gate 	if (bufp->st_mode & S_IFCHR) {
1348*7c478bd9Sstevel@tonic-gate 	    cnt = 1;
1349*7c478bd9Sstevel@tonic-gate 
1350*7c478bd9Sstevel@tonic-gate 	} else if (bufp->st_mode & S_IFDIR) {
1351*7c478bd9Sstevel@tonic-gate 	    /* each device file in the dir represents a slice */
1352*7c478bd9Sstevel@tonic-gate 	    DIR		*dirp;
1353*7c478bd9Sstevel@tonic-gate 
1354*7c478bd9Sstevel@tonic-gate 	    if ((dirp = fdopendir(fd)) != NULL) {
1355*7c478bd9Sstevel@tonic-gate 		struct dirent	*dentp;
1356*7c478bd9Sstevel@tonic-gate #ifdef _LP64
1357*7c478bd9Sstevel@tonic-gate 		struct dirent	*result;
1358*7c478bd9Sstevel@tonic-gate #endif
1359*7c478bd9Sstevel@tonic-gate 		char		devpath[MAXPATHLEN];
1360*7c478bd9Sstevel@tonic-gate 
1361*7c478bd9Sstevel@tonic-gate 		slice_rdsk2dsk(volm_path, devpath, sizeof (devpath));
1362*7c478bd9Sstevel@tonic-gate 
1363*7c478bd9Sstevel@tonic-gate 		dentp = (struct dirent *)malloc(sizeof (struct dirent) +
1364*7c478bd9Sstevel@tonic-gate 		    _PC_NAME_MAX + 1);
1365*7c478bd9Sstevel@tonic-gate 		if (dentp != NULL) {
1366*7c478bd9Sstevel@tonic-gate #ifdef _LP64
1367*7c478bd9Sstevel@tonic-gate 		    while (readdir_r(dirp, dentp, &result) != NULL) {
1368*7c478bd9Sstevel@tonic-gate #else
1369*7c478bd9Sstevel@tonic-gate 		    while (readdir_r(dirp, dentp) != NULL) {
1370*7c478bd9Sstevel@tonic-gate #endif
1371*7c478bd9Sstevel@tonic-gate 			int	dfd;
1372*7c478bd9Sstevel@tonic-gate 			char	slice_path[MAXPATHLEN];
1373*7c478bd9Sstevel@tonic-gate 
1374*7c478bd9Sstevel@tonic-gate 			if (libdiskmgt_str_eq(".", dentp->d_name) ||
1375*7c478bd9Sstevel@tonic-gate 			    libdiskmgt_str_eq("..", dentp->d_name)) {
1376*7c478bd9Sstevel@tonic-gate 			    continue;
1377*7c478bd9Sstevel@tonic-gate 			}
1378*7c478bd9Sstevel@tonic-gate 
1379*7c478bd9Sstevel@tonic-gate 			(void) snprintf(slice_path, sizeof (slice_path),
1380*7c478bd9Sstevel@tonic-gate 			    "%s/%s", devpath, dentp->d_name);
1381*7c478bd9Sstevel@tonic-gate 
1382*7c478bd9Sstevel@tonic-gate 			if ((dfd = open(slice_path, O_RDONLY|O_NDELAY)) >= 0) {
1383*7c478bd9Sstevel@tonic-gate 			    struct stat	buf;
1384*7c478bd9Sstevel@tonic-gate 
1385*7c478bd9Sstevel@tonic-gate 			    if (fstat(dfd, &buf) == 0 &&
1386*7c478bd9Sstevel@tonic-gate 				buf.st_mode & S_IFCHR) {
1387*7c478bd9Sstevel@tonic-gate 				cnt++;
1388*7c478bd9Sstevel@tonic-gate 			    }
1389*7c478bd9Sstevel@tonic-gate 			    (void) close(dfd);
1390*7c478bd9Sstevel@tonic-gate 			}
1391*7c478bd9Sstevel@tonic-gate 		    }
1392*7c478bd9Sstevel@tonic-gate 		    free(dentp);
1393*7c478bd9Sstevel@tonic-gate 		}
1394*7c478bd9Sstevel@tonic-gate 		/* don't call closedir since it closes the fd */
1395*7c478bd9Sstevel@tonic-gate 	    }
1396*7c478bd9Sstevel@tonic-gate 	} /* end of dir handling */
1397*7c478bd9Sstevel@tonic-gate 
1398*7c478bd9Sstevel@tonic-gate 	return (cnt);
1399*7c478bd9Sstevel@tonic-gate }
1400