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