xref: /titanic_53/usr/src/lib/libdiskmgt/common/partition.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 <sys/sunddi.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
37*7c478bd9Sstevel@tonic-gate #include <dirent.h>
38*7c478bd9Sstevel@tonic-gate #include <unistd.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include "libdiskmgt.h"
42*7c478bd9Sstevel@tonic-gate #include "disks_private.h"
43*7c478bd9Sstevel@tonic-gate #include "partition.h"
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #ifdef sparc
46*7c478bd9Sstevel@tonic-gate #define	les(val)	((((val)&0xFF)<<8)|(((val)>>8)&0xFF))
47*7c478bd9Sstevel@tonic-gate #define	lel(val)	(((unsigned)(les((val)&0x0000FFFF))<<16) | \
48*7c478bd9Sstevel@tonic-gate 			    (les((unsigned)((val)&0xffff0000)>>16)))
49*7c478bd9Sstevel@tonic-gate #else
50*7c478bd9Sstevel@tonic-gate #define	les(val)	(val)
51*7c478bd9Sstevel@tonic-gate #define	lel(val)	(val)
52*7c478bd9Sstevel@tonic-gate #endif
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate #define	ISIZE		FD_NUMPART * sizeof (struct ipart)
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate static int	desc_ok(descriptor_t *dp);
57*7c478bd9Sstevel@tonic-gate static int	get_attrs(descriptor_t *dp, struct ipart *iparts,
58*7c478bd9Sstevel@tonic-gate 		    nvlist_t *attrs);
59*7c478bd9Sstevel@tonic-gate static int	get_parts(disk_t *disk, struct ipart *iparts, char *opath,
60*7c478bd9Sstevel@tonic-gate 		    int opath_len);
61*7c478bd9Sstevel@tonic-gate static int	open_disk(disk_t *diskp, char *opath, int len);
62*7c478bd9Sstevel@tonic-gate static int	has_slices(descriptor_t *desc, int *errp);
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate descriptor_t **
65*7c478bd9Sstevel@tonic-gate partition_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type,
66*7c478bd9Sstevel@tonic-gate     int *errp)
67*7c478bd9Sstevel@tonic-gate {
68*7c478bd9Sstevel@tonic-gate 	if (!desc_ok(desc)) {
69*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
70*7c478bd9Sstevel@tonic-gate 	    return (NULL);
71*7c478bd9Sstevel@tonic-gate 	}
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate 	switch (type) {
74*7c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
75*7c478bd9Sstevel@tonic-gate 	    return (media_get_assocs(desc, errp));
76*7c478bd9Sstevel@tonic-gate 	case DM_SLICE:
77*7c478bd9Sstevel@tonic-gate 	    if (!has_slices(desc, errp)) {
78*7c478bd9Sstevel@tonic-gate 		if (*errp != 0) {
79*7c478bd9Sstevel@tonic-gate 		    return (NULL);
80*7c478bd9Sstevel@tonic-gate 		}
81*7c478bd9Sstevel@tonic-gate 		return (libdiskmgt_empty_desc_array(errp));
82*7c478bd9Sstevel@tonic-gate 	    }
83*7c478bd9Sstevel@tonic-gate 	    return (slice_get_assocs(desc, errp));
84*7c478bd9Sstevel@tonic-gate 	}
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 	*errp = EINVAL;
87*7c478bd9Sstevel@tonic-gate 	return (NULL);
88*7c478bd9Sstevel@tonic-gate }
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate /*
91*7c478bd9Sstevel@tonic-gate  * This is called by media/slice to get the associated partitions.
92*7c478bd9Sstevel@tonic-gate  * For a media desc. we just get all the partitions, but for a slice desc.
93*7c478bd9Sstevel@tonic-gate  * we just get the active solaris partition.
94*7c478bd9Sstevel@tonic-gate  */
95*7c478bd9Sstevel@tonic-gate descriptor_t **
96*7c478bd9Sstevel@tonic-gate partition_get_assocs(descriptor_t *desc, int *errp)
97*7c478bd9Sstevel@tonic-gate {
98*7c478bd9Sstevel@tonic-gate 	descriptor_t	**partitions;
99*7c478bd9Sstevel@tonic-gate 	int		pos;
100*7c478bd9Sstevel@tonic-gate 	int		i;
101*7c478bd9Sstevel@tonic-gate 	struct ipart	iparts[FD_NUMPART];
102*7c478bd9Sstevel@tonic-gate 	char		pname[MAXPATHLEN];
103*7c478bd9Sstevel@tonic-gate 	int		conv_flag = 0;
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 	if (get_parts(desc->p.disk, iparts, pname, sizeof (pname)) != 0) {
106*7c478bd9Sstevel@tonic-gate 	    return (libdiskmgt_empty_desc_array(errp));
107*7c478bd9Sstevel@tonic-gate 	}
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 	/* allocate the array for the descriptors */
110*7c478bd9Sstevel@tonic-gate 	partitions = (descriptor_t **)calloc(FD_NUMPART + 1,
111*7c478bd9Sstevel@tonic-gate 	    sizeof (descriptor_t *));
112*7c478bd9Sstevel@tonic-gate 	if (partitions == NULL) {
113*7c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
114*7c478bd9Sstevel@tonic-gate 	    return (NULL);
115*7c478bd9Sstevel@tonic-gate 	}
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate #ifdef i386
118*7c478bd9Sstevel@tonic-gate 	{
119*7c478bd9Sstevel@tonic-gate 	    /* convert part. name (e.g. c0d0p0) */
120*7c478bd9Sstevel@tonic-gate 	    int	len;
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate 	    len = strlen(pname);
123*7c478bd9Sstevel@tonic-gate 	    if (len > 1 && *(pname + (len - 2)) == 'p') {
124*7c478bd9Sstevel@tonic-gate 		conv_flag = 1;
125*7c478bd9Sstevel@tonic-gate 		*(pname + (len - 1)) = 0;
126*7c478bd9Sstevel@tonic-gate 	    }
127*7c478bd9Sstevel@tonic-gate 	}
128*7c478bd9Sstevel@tonic-gate #endif
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 	/*
131*7c478bd9Sstevel@tonic-gate 	 * If this is a slice desc. we need the first active solaris partition
132*7c478bd9Sstevel@tonic-gate 	 * and if there isn't one then we need the first solaris partition.
133*7c478bd9Sstevel@tonic-gate 	 */
134*7c478bd9Sstevel@tonic-gate 	if (desc->type == DM_SLICE) {
135*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < FD_NUMPART; i++) {
136*7c478bd9Sstevel@tonic-gate 		if (iparts[i].bootid == ACTIVE &&
137*7c478bd9Sstevel@tonic-gate 		    (iparts[i].systid == SUNIXOS ||
138*7c478bd9Sstevel@tonic-gate 		    iparts[i].systid == SUNIXOS2)) {
139*7c478bd9Sstevel@tonic-gate 			break;
140*7c478bd9Sstevel@tonic-gate 		}
141*7c478bd9Sstevel@tonic-gate 	    }
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 	    /* no active solaris part., try to get the first solaris part. */
144*7c478bd9Sstevel@tonic-gate 	    if (i >= FD_NUMPART) {
145*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
146*7c478bd9Sstevel@tonic-gate 		    if (iparts[i].systid == SUNIXOS ||
147*7c478bd9Sstevel@tonic-gate 			iparts[i].systid == SUNIXOS2) {
148*7c478bd9Sstevel@tonic-gate 			    break;
149*7c478bd9Sstevel@tonic-gate 		    }
150*7c478bd9Sstevel@tonic-gate 		}
151*7c478bd9Sstevel@tonic-gate 	    }
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	    if (i < FD_NUMPART) {
154*7c478bd9Sstevel@tonic-gate 		/* we found a solaris partition to use */
155*7c478bd9Sstevel@tonic-gate 		char	part_name[MAXPATHLEN];
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 		if (conv_flag) {
158*7c478bd9Sstevel@tonic-gate 		    /* convert part. name (e.g. c0d0p0) */
159*7c478bd9Sstevel@tonic-gate 		    (void) snprintf(part_name, sizeof (part_name), "%s%d",
160*7c478bd9Sstevel@tonic-gate 			pname, i);
161*7c478bd9Sstevel@tonic-gate 		} else {
162*7c478bd9Sstevel@tonic-gate 		    (void) snprintf(part_name, sizeof (part_name), "%d", i);
163*7c478bd9Sstevel@tonic-gate 		}
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 		/* the media name comes from the slice desc. */
166*7c478bd9Sstevel@tonic-gate 		partitions[0] = cache_get_desc(DM_PARTITION, desc->p.disk,
167*7c478bd9Sstevel@tonic-gate 		    part_name, desc->secondary_name, errp);
168*7c478bd9Sstevel@tonic-gate 		if (*errp != 0) {
169*7c478bd9Sstevel@tonic-gate 		    cache_free_descriptors(partitions);
170*7c478bd9Sstevel@tonic-gate 		    return (NULL);
171*7c478bd9Sstevel@tonic-gate 		}
172*7c478bd9Sstevel@tonic-gate 		partitions[1] = NULL;
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 		return (partitions);
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	    }
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 	    return (libdiskmgt_empty_desc_array(errp));
179*7c478bd9Sstevel@tonic-gate 	}
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	/* Must be for media, so get all the parts. */
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	pos = 0;
184*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
185*7c478bd9Sstevel@tonic-gate 	    if (iparts[i].systid != 0) {
186*7c478bd9Sstevel@tonic-gate 		char	part_name[MAXPATHLEN];
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 		if (conv_flag) {
189*7c478bd9Sstevel@tonic-gate 		    /* convert part. name (e.g. c0d0p0) */
190*7c478bd9Sstevel@tonic-gate 		    (void) snprintf(part_name, sizeof (part_name), "%s%d",
191*7c478bd9Sstevel@tonic-gate 			pname, i);
192*7c478bd9Sstevel@tonic-gate 		} else {
193*7c478bd9Sstevel@tonic-gate 		    (void) snprintf(part_name, sizeof (part_name), "%d", i);
194*7c478bd9Sstevel@tonic-gate 		}
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 		/* the media name comes from the media desc. */
197*7c478bd9Sstevel@tonic-gate 		partitions[pos] = cache_get_desc(DM_PARTITION, desc->p.disk,
198*7c478bd9Sstevel@tonic-gate 		    part_name, desc->name, errp);
199*7c478bd9Sstevel@tonic-gate 		if (*errp != 0) {
200*7c478bd9Sstevel@tonic-gate 		    cache_free_descriptors(partitions);
201*7c478bd9Sstevel@tonic-gate 		    return (NULL);
202*7c478bd9Sstevel@tonic-gate 		}
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 		pos++;
205*7c478bd9Sstevel@tonic-gate 	    }
206*7c478bd9Sstevel@tonic-gate 	}
207*7c478bd9Sstevel@tonic-gate 	partitions[pos] = NULL;
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 	*errp = 0;
210*7c478bd9Sstevel@tonic-gate 	return (partitions);
211*7c478bd9Sstevel@tonic-gate }
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate nvlist_t *
214*7c478bd9Sstevel@tonic-gate partition_get_attributes(descriptor_t *dp, int *errp)
215*7c478bd9Sstevel@tonic-gate {
216*7c478bd9Sstevel@tonic-gate 	nvlist_t	*attrs = NULL;
217*7c478bd9Sstevel@tonic-gate 	struct ipart	iparts[FD_NUMPART];
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	if (!desc_ok(dp)) {
220*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
221*7c478bd9Sstevel@tonic-gate 	    return (NULL);
222*7c478bd9Sstevel@tonic-gate 	}
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 	if ((*errp = get_parts(dp->p.disk, iparts, NULL, 0)) != 0) {
225*7c478bd9Sstevel@tonic-gate 	    return (NULL);
226*7c478bd9Sstevel@tonic-gate 	}
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
229*7c478bd9Sstevel@tonic-gate 	    *errp = ENOMEM;
230*7c478bd9Sstevel@tonic-gate 	    return (NULL);
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	if ((*errp = get_attrs(dp, iparts, attrs)) != 0) {
234*7c478bd9Sstevel@tonic-gate 	    nvlist_free(attrs);
235*7c478bd9Sstevel@tonic-gate 	    attrs = NULL;
236*7c478bd9Sstevel@tonic-gate 	}
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	return (attrs);
239*7c478bd9Sstevel@tonic-gate }
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate /*
242*7c478bd9Sstevel@tonic-gate  * Look for the partition by the partition number (which is not too useful).
243*7c478bd9Sstevel@tonic-gate  */
244*7c478bd9Sstevel@tonic-gate descriptor_t *
245*7c478bd9Sstevel@tonic-gate partition_get_descriptor_by_name(char *name, int *errp)
246*7c478bd9Sstevel@tonic-gate {
247*7c478bd9Sstevel@tonic-gate 	descriptor_t	**partitions;
248*7c478bd9Sstevel@tonic-gate 	int		i;
249*7c478bd9Sstevel@tonic-gate 	descriptor_t	*partition = NULL;
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	partitions = cache_get_descriptors(DM_PARTITION, errp);
252*7c478bd9Sstevel@tonic-gate 	if (*errp != 0) {
253*7c478bd9Sstevel@tonic-gate 	    return (NULL);
254*7c478bd9Sstevel@tonic-gate 	}
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 	for (i = 0; partitions[i]; i++) {
257*7c478bd9Sstevel@tonic-gate 	    if (libdiskmgt_str_eq(name, partitions[i]->name)) {
258*7c478bd9Sstevel@tonic-gate 		partition = partitions[i];
259*7c478bd9Sstevel@tonic-gate 	    } else {
260*7c478bd9Sstevel@tonic-gate 		/* clean up the unused descriptors */
261*7c478bd9Sstevel@tonic-gate 		cache_free_descriptor(partitions[i]);
262*7c478bd9Sstevel@tonic-gate 	    }
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 	free(partitions);
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	if (partition == NULL) {
267*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 	return (partition);
271*7c478bd9Sstevel@tonic-gate }
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
274*7c478bd9Sstevel@tonic-gate descriptor_t **
275*7c478bd9Sstevel@tonic-gate partition_get_descriptors(int filter[], int *errp)
276*7c478bd9Sstevel@tonic-gate {
277*7c478bd9Sstevel@tonic-gate 	return (cache_get_descriptors(DM_PARTITION, errp));
278*7c478bd9Sstevel@tonic-gate }
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate char *
281*7c478bd9Sstevel@tonic-gate partition_get_name(descriptor_t *desc)
282*7c478bd9Sstevel@tonic-gate {
283*7c478bd9Sstevel@tonic-gate 	return (desc->name);
284*7c478bd9Sstevel@tonic-gate }
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
287*7c478bd9Sstevel@tonic-gate nvlist_t *
288*7c478bd9Sstevel@tonic-gate partition_get_stats(descriptor_t *dp, int stat_type, int *errp)
289*7c478bd9Sstevel@tonic-gate {
290*7c478bd9Sstevel@tonic-gate 	/* There are no stat types defined for partitions */
291*7c478bd9Sstevel@tonic-gate 	*errp = EINVAL;
292*7c478bd9Sstevel@tonic-gate 	return (NULL);
293*7c478bd9Sstevel@tonic-gate }
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
296*7c478bd9Sstevel@tonic-gate int
297*7c478bd9Sstevel@tonic-gate partition_has_fdisk(disk_t *dp, int fd)
298*7c478bd9Sstevel@tonic-gate {
299*7c478bd9Sstevel@tonic-gate 	char		bootsect[512 * 3]; /* 3 sectors to be safe */
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate #ifdef sparc
302*7c478bd9Sstevel@tonic-gate 	if (dp->drv_type == DM_DT_FIXED) {
303*7c478bd9Sstevel@tonic-gate 	    /* on sparc, only removable media can have fdisk parts. */
304*7c478bd9Sstevel@tonic-gate 	    return (0);
305*7c478bd9Sstevel@tonic-gate 	}
306*7c478bd9Sstevel@tonic-gate #endif
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	/*
309*7c478bd9Sstevel@tonic-gate 	 * We assume the caller already made sure media was inserted and
310*7c478bd9Sstevel@tonic-gate 	 * spun up.
311*7c478bd9Sstevel@tonic-gate 	 */
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	if ((ioctl(fd, DKIOCGMBOOT, bootsect) < 0) && (errno != ENOTTY)) {
314*7c478bd9Sstevel@tonic-gate 	    return (0);
315*7c478bd9Sstevel@tonic-gate 	}
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	return (1);
318*7c478bd9Sstevel@tonic-gate }
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate /*
321*7c478bd9Sstevel@tonic-gate  * A partition descriptor points to a disk, the name is the partition number
322*7c478bd9Sstevel@tonic-gate  * and the secondary name is the media name.
323*7c478bd9Sstevel@tonic-gate  */
324*7c478bd9Sstevel@tonic-gate int
325*7c478bd9Sstevel@tonic-gate partition_make_descriptors()
326*7c478bd9Sstevel@tonic-gate {
327*7c478bd9Sstevel@tonic-gate 	int		error;
328*7c478bd9Sstevel@tonic-gate 	disk_t		*dp;
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	dp = cache_get_disklist();
331*7c478bd9Sstevel@tonic-gate 	while (dp != NULL) {
332*7c478bd9Sstevel@tonic-gate 	    struct ipart	iparts[FD_NUMPART];
333*7c478bd9Sstevel@tonic-gate 	    char		pname[MAXPATHLEN];
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	    if (get_parts(dp, iparts, pname, sizeof (pname)) == 0) {
336*7c478bd9Sstevel@tonic-gate 		int	i;
337*7c478bd9Sstevel@tonic-gate 		char	mname[MAXPATHLEN];
338*7c478bd9Sstevel@tonic-gate 		int	conv_flag = 0;
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate #ifdef i386
341*7c478bd9Sstevel@tonic-gate 		/* convert part. name (e.g. c0d0p0) */
342*7c478bd9Sstevel@tonic-gate 		int	len;
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 		len = strlen(pname);
345*7c478bd9Sstevel@tonic-gate 		if (len > 1 && *(pname + (len - 2)) == 'p') {
346*7c478bd9Sstevel@tonic-gate 		    conv_flag = 1;
347*7c478bd9Sstevel@tonic-gate 		    *(pname + (len - 1)) = 0;
348*7c478bd9Sstevel@tonic-gate 		}
349*7c478bd9Sstevel@tonic-gate #endif
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 		mname[0] = 0;
352*7c478bd9Sstevel@tonic-gate 		(void) media_read_name(dp, mname, sizeof (mname));
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
355*7c478bd9Sstevel@tonic-gate 		    if (iparts[i].systid != 0) {
356*7c478bd9Sstevel@tonic-gate 			char	part_name[MAXPATHLEN];
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 			if (conv_flag) {
359*7c478bd9Sstevel@tonic-gate 			    /* convert part. name (e.g. c0d0p0) */
360*7c478bd9Sstevel@tonic-gate 			    (void) snprintf(part_name, sizeof (part_name),
361*7c478bd9Sstevel@tonic-gate 				"%s%d", pname, i);
362*7c478bd9Sstevel@tonic-gate 			} else {
363*7c478bd9Sstevel@tonic-gate 			    (void) snprintf(part_name, sizeof (part_name),
364*7c478bd9Sstevel@tonic-gate 				"%d", i);
365*7c478bd9Sstevel@tonic-gate 			}
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate 			cache_load_desc(DM_PARTITION, dp, part_name, mname,
368*7c478bd9Sstevel@tonic-gate 			    &error);
369*7c478bd9Sstevel@tonic-gate 			if (error != 0) {
370*7c478bd9Sstevel@tonic-gate 			    return (error);
371*7c478bd9Sstevel@tonic-gate 			}
372*7c478bd9Sstevel@tonic-gate 		    }
373*7c478bd9Sstevel@tonic-gate 		}
374*7c478bd9Sstevel@tonic-gate 	    }
375*7c478bd9Sstevel@tonic-gate 	    dp = dp->next;
376*7c478bd9Sstevel@tonic-gate 	}
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate 	return (0);
379*7c478bd9Sstevel@tonic-gate }
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate static int
382*7c478bd9Sstevel@tonic-gate get_attrs(descriptor_t *dp, struct ipart *iparts, nvlist_t *attrs)
383*7c478bd9Sstevel@tonic-gate {
384*7c478bd9Sstevel@tonic-gate 	char		*p;
385*7c478bd9Sstevel@tonic-gate 	int		part_num;
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	/*
388*7c478bd9Sstevel@tonic-gate 	 * We already made sure the media was loaded and ready in the
389*7c478bd9Sstevel@tonic-gate 	 * get_parts call within partition_get_attributes.
390*7c478bd9Sstevel@tonic-gate 	 */
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate 	p = strrchr(dp->name, 'p');
393*7c478bd9Sstevel@tonic-gate 	if (p == NULL) {
394*7c478bd9Sstevel@tonic-gate 	    p = dp->name;
395*7c478bd9Sstevel@tonic-gate 	} else {
396*7c478bd9Sstevel@tonic-gate 	    p++;
397*7c478bd9Sstevel@tonic-gate 	}
398*7c478bd9Sstevel@tonic-gate 	part_num = atoi(p);
399*7c478bd9Sstevel@tonic-gate 	if (part_num >= FD_NUMPART || iparts[part_num].systid == 0) {
400*7c478bd9Sstevel@tonic-gate 	    return (ENODEV);
401*7c478bd9Sstevel@tonic-gate 	}
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 	/* we found the partition */
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_BOOTID,
406*7c478bd9Sstevel@tonic-gate 	    (unsigned int)iparts[part_num].bootid) != 0) {
407*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
408*7c478bd9Sstevel@tonic-gate 	}
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_PTYPE,
411*7c478bd9Sstevel@tonic-gate 	    (unsigned int)iparts[part_num].systid) != 0) {
412*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
413*7c478bd9Sstevel@tonic-gate 	}
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_BHEAD,
416*7c478bd9Sstevel@tonic-gate 	    (unsigned int)iparts[part_num].beghead) != 0) {
417*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
418*7c478bd9Sstevel@tonic-gate 	}
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_BSECT,
421*7c478bd9Sstevel@tonic-gate 	    (unsigned int)((iparts[part_num].begsect) & 0x3f)) != 0) {
422*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
423*7c478bd9Sstevel@tonic-gate 	}
424*7c478bd9Sstevel@tonic-gate 
425*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_BCYL, (unsigned int)
426*7c478bd9Sstevel@tonic-gate 	    ((iparts[part_num].begcyl & 0xff) |
427*7c478bd9Sstevel@tonic-gate 	    ((iparts[part_num].begsect & 0xc0) << 2))) != 0) {
428*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
429*7c478bd9Sstevel@tonic-gate 	}
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_EHEAD,
432*7c478bd9Sstevel@tonic-gate 	    (unsigned int)iparts[part_num].endhead) != 0) {
433*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
434*7c478bd9Sstevel@tonic-gate 	}
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_ESECT,
437*7c478bd9Sstevel@tonic-gate 	    (unsigned int)((iparts[part_num].endsect) & 0x3f)) != 0) {
438*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
439*7c478bd9Sstevel@tonic-gate 	}
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_ECYL, (unsigned int)
442*7c478bd9Sstevel@tonic-gate 	    ((iparts[part_num].endcyl & 0xff) |
443*7c478bd9Sstevel@tonic-gate 	    ((iparts[part_num].endsect & 0xc0) << 2))) != 0) {
444*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
445*7c478bd9Sstevel@tonic-gate 	}
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_RELSECT,
448*7c478bd9Sstevel@tonic-gate 	    (unsigned int)iparts[part_num].relsect) != 0) {
449*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
450*7c478bd9Sstevel@tonic-gate 	}
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 	if (nvlist_add_uint32(attrs, DM_NSECTORS,
453*7c478bd9Sstevel@tonic-gate 	    (unsigned int)iparts[part_num].numsect) != 0) {
454*7c478bd9Sstevel@tonic-gate 	    return (ENOMEM);
455*7c478bd9Sstevel@tonic-gate 	}
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	return (0);
458*7c478bd9Sstevel@tonic-gate }
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate static int
461*7c478bd9Sstevel@tonic-gate get_parts(disk_t *disk, struct ipart *iparts, char *opath, int opath_len)
462*7c478bd9Sstevel@tonic-gate {
463*7c478bd9Sstevel@tonic-gate 	int		fd;
464*7c478bd9Sstevel@tonic-gate 	struct dk_minfo	minfo;
465*7c478bd9Sstevel@tonic-gate 	struct mboot	bootblk;
466*7c478bd9Sstevel@tonic-gate 	char		bootsect[512];
467*7c478bd9Sstevel@tonic-gate 	int		i;
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 	/* Can't use drive_open_disk since we need the partition dev name. */
470*7c478bd9Sstevel@tonic-gate 	if ((fd = open_disk(disk, opath, opath_len)) < 0) {
471*7c478bd9Sstevel@tonic-gate 	    return (ENODEV);
472*7c478bd9Sstevel@tonic-gate 	}
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 	/* First make sure media is inserted and spun up. */
475*7c478bd9Sstevel@tonic-gate 	if (!media_read_info(fd, &minfo)) {
476*7c478bd9Sstevel@tonic-gate #ifdef i386
477*7c478bd9Sstevel@tonic-gate 	    /* XXX Work around bug 4725434 */
478*7c478bd9Sstevel@tonic-gate 	    if (disk->removable) {
479*7c478bd9Sstevel@tonic-gate #endif
480*7c478bd9Sstevel@tonic-gate 	    (void) close(fd);
481*7c478bd9Sstevel@tonic-gate 	    return (ENODEV);
482*7c478bd9Sstevel@tonic-gate #ifdef i386
483*7c478bd9Sstevel@tonic-gate 	    }
484*7c478bd9Sstevel@tonic-gate #endif
485*7c478bd9Sstevel@tonic-gate 	}
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	if (!partition_has_fdisk(disk, fd)) {
488*7c478bd9Sstevel@tonic-gate 	    (void) close(fd);
489*7c478bd9Sstevel@tonic-gate 	    return (ENOTTY);
490*7c478bd9Sstevel@tonic-gate 	}
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	if (lseek(fd, 0, 0) == -1) {
493*7c478bd9Sstevel@tonic-gate 	    (void) close(fd);
494*7c478bd9Sstevel@tonic-gate 	    return (ENODEV);
495*7c478bd9Sstevel@tonic-gate 	}
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 	if (read(fd, bootsect, 512) != 512) {
498*7c478bd9Sstevel@tonic-gate 	    (void) close(fd);
499*7c478bd9Sstevel@tonic-gate 	    return (ENODEV);
500*7c478bd9Sstevel@tonic-gate 	}
501*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate 	(void) memcpy(&bootblk, bootsect, sizeof (bootblk));
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	if (les(bootblk.signature) != MBB_MAGIC)  {
506*7c478bd9Sstevel@tonic-gate 	    return (ENOTTY);
507*7c478bd9Sstevel@tonic-gate 	}
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate 	(void) memcpy(iparts, bootblk.parts, ISIZE);
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
512*7c478bd9Sstevel@tonic-gate 	    if (iparts[i].systid != 0) {
513*7c478bd9Sstevel@tonic-gate 		iparts[i].relsect = lel(iparts[i].relsect);
514*7c478bd9Sstevel@tonic-gate 		iparts[i].numsect = lel(iparts[i].numsect);
515*7c478bd9Sstevel@tonic-gate 	    }
516*7c478bd9Sstevel@tonic-gate 	}
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 	return (0);
519*7c478bd9Sstevel@tonic-gate }
520*7c478bd9Sstevel@tonic-gate /* return 1 if the partition descriptor is still valid, 0 if not. */
521*7c478bd9Sstevel@tonic-gate static int
522*7c478bd9Sstevel@tonic-gate desc_ok(descriptor_t *dp)
523*7c478bd9Sstevel@tonic-gate {
524*7c478bd9Sstevel@tonic-gate 	/* First verify the media name for removable media */
525*7c478bd9Sstevel@tonic-gate 	if (dp->p.disk->removable) {
526*7c478bd9Sstevel@tonic-gate 	    char	mname[MAXPATHLEN];
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	    if (!media_read_name(dp->p.disk, mname, sizeof (mname))) {
529*7c478bd9Sstevel@tonic-gate 		return (0);
530*7c478bd9Sstevel@tonic-gate 	    }
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	    if (mname[0] == 0) {
533*7c478bd9Sstevel@tonic-gate 		return (libdiskmgt_str_eq(dp->secondary_name, NULL));
534*7c478bd9Sstevel@tonic-gate 	    } else {
535*7c478bd9Sstevel@tonic-gate 		return (libdiskmgt_str_eq(dp->secondary_name, mname));
536*7c478bd9Sstevel@tonic-gate 	    }
537*7c478bd9Sstevel@tonic-gate 	}
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate 	/*
540*7c478bd9Sstevel@tonic-gate 	 * We could verify the partition is still there but this is kind of
541*7c478bd9Sstevel@tonic-gate 	 * expensive and other code down the line will do that (e.g. see
542*7c478bd9Sstevel@tonic-gate 	 * get_attrs).
543*7c478bd9Sstevel@tonic-gate 	 */
544*7c478bd9Sstevel@tonic-gate 
545*7c478bd9Sstevel@tonic-gate 	return (1);
546*7c478bd9Sstevel@tonic-gate }
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate /*
549*7c478bd9Sstevel@tonic-gate  * Return 1 if partition has slices, 0 if not.
550*7c478bd9Sstevel@tonic-gate  */
551*7c478bd9Sstevel@tonic-gate static int
552*7c478bd9Sstevel@tonic-gate has_slices(descriptor_t *desc, int *errp)
553*7c478bd9Sstevel@tonic-gate {
554*7c478bd9Sstevel@tonic-gate 	int		pnum;
555*7c478bd9Sstevel@tonic-gate 	int		i;
556*7c478bd9Sstevel@tonic-gate 	char		*p;
557*7c478bd9Sstevel@tonic-gate 	struct ipart	iparts[FD_NUMPART];
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 	if (get_parts(desc->p.disk, iparts, NULL, 0) != 0) {
560*7c478bd9Sstevel@tonic-gate 	    *errp = ENODEV;
561*7c478bd9Sstevel@tonic-gate 	    return (0);
562*7c478bd9Sstevel@tonic-gate 	}
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate 	p = strrchr(desc->name, 'p');
565*7c478bd9Sstevel@tonic-gate 	if (p == NULL) {
566*7c478bd9Sstevel@tonic-gate 	    p = desc->name;
567*7c478bd9Sstevel@tonic-gate 	} else {
568*7c478bd9Sstevel@tonic-gate 	    p++;
569*7c478bd9Sstevel@tonic-gate 	}
570*7c478bd9Sstevel@tonic-gate 	pnum = atoi(p);
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 	/*
573*7c478bd9Sstevel@tonic-gate 	 * Slices are associated with the active solaris partition or if there
574*7c478bd9Sstevel@tonic-gate 	 * is no active solaris partition, then the first solaris partition.
575*7c478bd9Sstevel@tonic-gate 	 */
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 	*errp = 0;
578*7c478bd9Sstevel@tonic-gate 	if (iparts[pnum].bootid == ACTIVE &&
579*7c478bd9Sstevel@tonic-gate 	    (iparts[pnum].systid == SUNIXOS ||
580*7c478bd9Sstevel@tonic-gate 	    iparts[pnum].systid == SUNIXOS2)) {
581*7c478bd9Sstevel@tonic-gate 		return (1);
582*7c478bd9Sstevel@tonic-gate 	} else {
583*7c478bd9Sstevel@tonic-gate 	    int	active = 0;
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate 	    /* Check if there are no active solaris partitions. */
586*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < FD_NUMPART; i++) {
587*7c478bd9Sstevel@tonic-gate 		if (iparts[i].bootid == ACTIVE &&
588*7c478bd9Sstevel@tonic-gate 		    (iparts[i].systid == SUNIXOS ||
589*7c478bd9Sstevel@tonic-gate 		    iparts[i].systid == SUNIXOS2)) {
590*7c478bd9Sstevel@tonic-gate 			active = 1;
591*7c478bd9Sstevel@tonic-gate 			break;
592*7c478bd9Sstevel@tonic-gate 		}
593*7c478bd9Sstevel@tonic-gate 	    }
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 	    if (!active) {
596*7c478bd9Sstevel@tonic-gate 		/* Check if this is the first solaris partition. */
597*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
598*7c478bd9Sstevel@tonic-gate 		    if (iparts[i].systid == SUNIXOS ||
599*7c478bd9Sstevel@tonic-gate 			iparts[i].systid == SUNIXOS2) {
600*7c478bd9Sstevel@tonic-gate 			    break;
601*7c478bd9Sstevel@tonic-gate 		    }
602*7c478bd9Sstevel@tonic-gate 		}
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 		if (i < FD_NUMPART && i == pnum) {
605*7c478bd9Sstevel@tonic-gate 		    return (1);
606*7c478bd9Sstevel@tonic-gate 		}
607*7c478bd9Sstevel@tonic-gate 	    }
608*7c478bd9Sstevel@tonic-gate 	}
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 	return (0);
611*7c478bd9Sstevel@tonic-gate }
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate static int
614*7c478bd9Sstevel@tonic-gate open_disk(disk_t *diskp, char *opath, int len)
615*7c478bd9Sstevel@tonic-gate {
616*7c478bd9Sstevel@tonic-gate 	char	rmmedia_devpath[MAXPATHLEN];
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate 	if (diskp->removable && media_get_volm_path(diskp, rmmedia_devpath,
619*7c478bd9Sstevel@tonic-gate 	    sizeof (rmmedia_devpath))) {
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate 	    int		fd;
622*7c478bd9Sstevel@tonic-gate 	    struct stat	buf;
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	    if (rmmedia_devpath[0] == 0) {
625*7c478bd9Sstevel@tonic-gate 		/* removable but no media */
626*7c478bd9Sstevel@tonic-gate 		return (-1);
627*7c478bd9Sstevel@tonic-gate 	    }
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate 	    if ((fd = open(rmmedia_devpath, O_RDONLY|O_NDELAY)) < 0) {
630*7c478bd9Sstevel@tonic-gate 		return (-1);
631*7c478bd9Sstevel@tonic-gate 	    }
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 	    if (fstat(fd, &buf) != 0) {
634*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
635*7c478bd9Sstevel@tonic-gate 		return (-1);
636*7c478bd9Sstevel@tonic-gate 	    }
637*7c478bd9Sstevel@tonic-gate 
638*7c478bd9Sstevel@tonic-gate 	    if (buf.st_mode & S_IFCHR) {
639*7c478bd9Sstevel@tonic-gate 		/* opened, is device, so done */
640*7c478bd9Sstevel@tonic-gate 		if (opath != NULL) {
641*7c478bd9Sstevel@tonic-gate 		    (void) strlcpy(opath, rmmedia_devpath, len);
642*7c478bd9Sstevel@tonic-gate 		}
643*7c478bd9Sstevel@tonic-gate 		return (fd);
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 	    } else if (buf.st_mode & S_IFDIR) {
646*7c478bd9Sstevel@tonic-gate 		/* disk w/ slices so handle the directory */
647*7c478bd9Sstevel@tonic-gate 		DIR		*dirp;
648*7c478bd9Sstevel@tonic-gate 		struct dirent	*dentp;
649*7c478bd9Sstevel@tonic-gate 		int		dfd;
650*7c478bd9Sstevel@tonic-gate #ifdef _LP64
651*7c478bd9Sstevel@tonic-gate 		struct dirent	*result;
652*7c478bd9Sstevel@tonic-gate #endif
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate 		/* each device file in the dir represents a slice */
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 		if ((dirp = fdopendir(fd)) == NULL) {
657*7c478bd9Sstevel@tonic-gate 		    (void) close(fd);
658*7c478bd9Sstevel@tonic-gate 		    return (-1);
659*7c478bd9Sstevel@tonic-gate 		}
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 		if ((dentp = (struct dirent *)malloc(sizeof (struct dirent) +
662*7c478bd9Sstevel@tonic-gate 		    _PC_NAME_MAX + 1)) == NULL) {
663*7c478bd9Sstevel@tonic-gate 		    /* out of memory */
664*7c478bd9Sstevel@tonic-gate 		    (void) close(fd);
665*7c478bd9Sstevel@tonic-gate 		    return (-1);
666*7c478bd9Sstevel@tonic-gate 		}
667*7c478bd9Sstevel@tonic-gate #ifdef _LP64
668*7c478bd9Sstevel@tonic-gate 		while (readdir_r(dirp, dentp, &result) != NULL) {
669*7c478bd9Sstevel@tonic-gate #else
670*7c478bd9Sstevel@tonic-gate 		while (readdir_r(dirp, dentp) != NULL) {
671*7c478bd9Sstevel@tonic-gate #endif
672*7c478bd9Sstevel@tonic-gate 		    char	slice_path[MAXPATHLEN];
673*7c478bd9Sstevel@tonic-gate 
674*7c478bd9Sstevel@tonic-gate 		    if (libdiskmgt_str_eq(".", dentp->d_name) ||
675*7c478bd9Sstevel@tonic-gate 			libdiskmgt_str_eq("..", dentp->d_name)) {
676*7c478bd9Sstevel@tonic-gate 			continue;
677*7c478bd9Sstevel@tonic-gate 		    }
678*7c478bd9Sstevel@tonic-gate 
679*7c478bd9Sstevel@tonic-gate 		    (void) snprintf(slice_path, sizeof (slice_path), "%s/%s",
680*7c478bd9Sstevel@tonic-gate 			rmmedia_devpath, dentp->d_name);
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate 		    if ((dfd = open(slice_path, O_RDONLY|O_NDELAY)) < 0) {
683*7c478bd9Sstevel@tonic-gate 			continue;
684*7c478bd9Sstevel@tonic-gate 		    }
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 		    if (fstat(dfd, &buf) == 0 && (buf.st_mode & S_IFCHR)) {
687*7c478bd9Sstevel@tonic-gate 			/* opened, is device, so done */
688*7c478bd9Sstevel@tonic-gate 			free(dentp);
689*7c478bd9Sstevel@tonic-gate 			(void) close(fd);
690*7c478bd9Sstevel@tonic-gate 			if (opath != NULL) {
691*7c478bd9Sstevel@tonic-gate 			    (void) strlcpy(opath, slice_path, len);
692*7c478bd9Sstevel@tonic-gate 			}
693*7c478bd9Sstevel@tonic-gate 			return (dfd);
694*7c478bd9Sstevel@tonic-gate 		    }
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 		    /* not a device, keep looking */
697*7c478bd9Sstevel@tonic-gate 		    (void) close(dfd);
698*7c478bd9Sstevel@tonic-gate 		}
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate 		/* did not find a device under the rmmedia_path */
701*7c478bd9Sstevel@tonic-gate 		free(dentp);
702*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
703*7c478bd9Sstevel@tonic-gate 	    }
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	    /* didn't find a device under volume management control */
706*7c478bd9Sstevel@tonic-gate 	    return (-1);
707*7c478bd9Sstevel@tonic-gate 	}
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate 	/*
710*7c478bd9Sstevel@tonic-gate 	 * Not removable media under volume management control so just open the
711*7c478bd9Sstevel@tonic-gate 	 * first devpath.
712*7c478bd9Sstevel@tonic-gate 	 */
713*7c478bd9Sstevel@tonic-gate 	if (diskp->aliases != NULL && diskp->aliases->devpaths != NULL) {
714*7c478bd9Sstevel@tonic-gate #ifdef sparc
715*7c478bd9Sstevel@tonic-gate 	    if (opath != NULL) {
716*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(opath, diskp->aliases->devpaths->devpath, len);
717*7c478bd9Sstevel@tonic-gate 	    }
718*7c478bd9Sstevel@tonic-gate 	    return (open(diskp->aliases->devpaths->devpath, O_RDONLY|O_NDELAY));
719*7c478bd9Sstevel@tonic-gate #else
720*7c478bd9Sstevel@tonic-gate 	    /* On intel we need to open partition device (e.g. c0d0p0). */
721*7c478bd9Sstevel@tonic-gate 	    char	part_dev[MAXPATHLEN];
722*7c478bd9Sstevel@tonic-gate 	    char	*p;
723*7c478bd9Sstevel@tonic-gate 
724*7c478bd9Sstevel@tonic-gate 	    (void) strlcpy(part_dev, diskp->aliases->devpaths->devpath,
725*7c478bd9Sstevel@tonic-gate 		sizeof (part_dev));
726*7c478bd9Sstevel@tonic-gate 	    p = strrchr(part_dev, '/');
727*7c478bd9Sstevel@tonic-gate 	    if (p == NULL) {
728*7c478bd9Sstevel@tonic-gate 		p = strrchr(part_dev, 's');
729*7c478bd9Sstevel@tonic-gate 		if (p != NULL) {
730*7c478bd9Sstevel@tonic-gate 		    *p = 'p';
731*7c478bd9Sstevel@tonic-gate 		}
732*7c478bd9Sstevel@tonic-gate 	    } else {
733*7c478bd9Sstevel@tonic-gate 		char *ps;
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate 		*p = 0;
736*7c478bd9Sstevel@tonic-gate 		ps = strrchr((p + 1), 's');
737*7c478bd9Sstevel@tonic-gate 		if (ps != NULL) {
738*7c478bd9Sstevel@tonic-gate 		    *ps = 'p';
739*7c478bd9Sstevel@tonic-gate 		}
740*7c478bd9Sstevel@tonic-gate 		*p = '/';
741*7c478bd9Sstevel@tonic-gate 	    }
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 	    if (opath != NULL) {
744*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(opath, part_dev, len);
745*7c478bd9Sstevel@tonic-gate 	    }
746*7c478bd9Sstevel@tonic-gate 	    return (open(part_dev, O_RDONLY|O_NDELAY));
747*7c478bd9Sstevel@tonic-gate #endif
748*7c478bd9Sstevel@tonic-gate 	}
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 	return (-1);
751*7c478bd9Sstevel@tonic-gate }
752