1*45916cd2Sjpk /* 2*45916cd2Sjpk * CDDL HEADER START 3*45916cd2Sjpk * 4*45916cd2Sjpk * The contents of this file are subject to the terms of the 5*45916cd2Sjpk * Common Development and Distribution License (the "License"). 6*45916cd2Sjpk * You may not use this file except in compliance with the License. 7*45916cd2Sjpk * 8*45916cd2Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*45916cd2Sjpk * or http://www.opensolaris.org/os/licensing. 10*45916cd2Sjpk * See the License for the specific language governing permissions 11*45916cd2Sjpk * and limitations under the License. 12*45916cd2Sjpk * 13*45916cd2Sjpk * When distributing Covered Code, include this CDDL HEADER in each 14*45916cd2Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*45916cd2Sjpk * If applicable, add the following below this CDDL HEADER, with the 16*45916cd2Sjpk * fields enclosed by brackets "[]" replaced with your own identifying 17*45916cd2Sjpk * information: Portions Copyright [yyyy] [name of copyright owner] 18*45916cd2Sjpk * 19*45916cd2Sjpk * CDDL HEADER END 20*45916cd2Sjpk */ 21*45916cd2Sjpk 22*45916cd2Sjpk /* 23*45916cd2Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*45916cd2Sjpk * Use is subject to license terms. 25*45916cd2Sjpk */ 26*45916cd2Sjpk 27*45916cd2Sjpk #pragma ident "%Z%%M% %I% %E% SMI" 28*45916cd2Sjpk 29*45916cd2Sjpk /* 30*45916cd2Sjpk * Device allocation related work. 31*45916cd2Sjpk */ 32*45916cd2Sjpk 33*45916cd2Sjpk #include <stdio.h> 34*45916cd2Sjpk #include <stdlib.h> 35*45916cd2Sjpk #include <errno.h> 36*45916cd2Sjpk #include <string.h> 37*45916cd2Sjpk #include <strings.h> 38*45916cd2Sjpk #include <unistd.h> 39*45916cd2Sjpk #include <fcntl.h> 40*45916cd2Sjpk #include <sys/types.h> 41*45916cd2Sjpk #include <sys/stat.h> 42*45916cd2Sjpk #include <sys/dkio.h> 43*45916cd2Sjpk #include <sys/wait.h> 44*45916cd2Sjpk #include <bsm/devalloc.h> 45*45916cd2Sjpk 46*45916cd2Sjpk #define DEALLOCATE "/usr/sbin/deallocate" 47*45916cd2Sjpk #define MKDEVALLOC "/usr/sbin/mkdevalloc" 48*45916cd2Sjpk 49*45916cd2Sjpk static void _update_dev(deventry_t *, int, char *); 50*45916cd2Sjpk static int _make_db(); 51*45916cd2Sjpk 52*45916cd2Sjpk 53*45916cd2Sjpk /* 54*45916cd2Sjpk * _da_check_for_usb 55*45916cd2Sjpk * returns 1 if device pointed by 'link' is a removable hotplugged 56*45916cd2Sjpk * else returns 0. 57*45916cd2Sjpk */ 58*45916cd2Sjpk int 59*45916cd2Sjpk _da_check_for_usb(char *link, char *root_dir) 60*45916cd2Sjpk { 61*45916cd2Sjpk int fd = -1; 62*45916cd2Sjpk int len, dstsize; 63*45916cd2Sjpk int removable = 0; 64*45916cd2Sjpk char *p = NULL; 65*45916cd2Sjpk char path[MAXPATHLEN]; 66*45916cd2Sjpk 67*45916cd2Sjpk dstsize = sizeof (path); 68*45916cd2Sjpk if (strcmp(root_dir, "") != 0) { 69*45916cd2Sjpk if (strlcat(path, root_dir, dstsize) >= dstsize) 70*45916cd2Sjpk return (0); 71*45916cd2Sjpk len = strlen(path); 72*45916cd2Sjpk } else { 73*45916cd2Sjpk len = 0; 74*45916cd2Sjpk } 75*45916cd2Sjpk if (strstr(link, "rdsk")) { 76*45916cd2Sjpk (void) snprintf(path, dstsize - len, "%s", link); 77*45916cd2Sjpk } else if (strstr(link, "dsk")) { 78*45916cd2Sjpk p = rindex(link, '/'); 79*45916cd2Sjpk if (p == NULL) 80*45916cd2Sjpk return (0); 81*45916cd2Sjpk p++; 82*45916cd2Sjpk (void) snprintf(path, dstsize - len, "%s%s", "/dev/rdsk/", p); 83*45916cd2Sjpk } else { 84*45916cd2Sjpk return (0); 85*45916cd2Sjpk } 86*45916cd2Sjpk 87*45916cd2Sjpk if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0) 88*45916cd2Sjpk return (0); 89*45916cd2Sjpk (void) ioctl(fd, DKIOCREMOVABLE, &removable); 90*45916cd2Sjpk (void) close(fd); 91*45916cd2Sjpk 92*45916cd2Sjpk return (removable); 93*45916cd2Sjpk } 94*45916cd2Sjpk 95*45916cd2Sjpk /* 96*45916cd2Sjpk * _reset_devalloc 97*45916cd2Sjpk * If device allocation is being turned on, creates device_allocate 98*45916cd2Sjpk * device_maps if they do not exist. 99*45916cd2Sjpk * Puts DEVICE_ALLOCATION=ON/OFF in device_allocate to indicate if 100*45916cd2Sjpk * device allocation is on/off. 101*45916cd2Sjpk */ 102*45916cd2Sjpk void 103*45916cd2Sjpk _reset_devalloc(int action) 104*45916cd2Sjpk { 105*45916cd2Sjpk da_args dargs; 106*45916cd2Sjpk 107*45916cd2Sjpk if (action == DA_ON) 108*45916cd2Sjpk (void) _make_db(); 109*45916cd2Sjpk else if ((action == DA_OFF) && (open(DEVALLOC, O_RDONLY) == -1)) 110*45916cd2Sjpk return; 111*45916cd2Sjpk 112*45916cd2Sjpk if (action == DA_ON) 113*45916cd2Sjpk dargs.optflag = DA_ON; 114*45916cd2Sjpk else if (action == DA_OFF) 115*45916cd2Sjpk dargs.optflag = DA_OFF | DA_ALLOC_ONLY; 116*45916cd2Sjpk 117*45916cd2Sjpk dargs.rootdir = NULL; 118*45916cd2Sjpk dargs.devnames = NULL; 119*45916cd2Sjpk dargs.devinfo = NULL; 120*45916cd2Sjpk 121*45916cd2Sjpk (void) da_update_device(&dargs); 122*45916cd2Sjpk } 123*45916cd2Sjpk 124*45916cd2Sjpk /* 125*45916cd2Sjpk * _make_db 126*45916cd2Sjpk * execs /usr/sbin/mkdevalloc to create device_allocate and 127*45916cd2Sjpk * device_maps. 128*45916cd2Sjpk */ 129*45916cd2Sjpk static int 130*45916cd2Sjpk _make_db() 131*45916cd2Sjpk { 132*45916cd2Sjpk int status; 133*45916cd2Sjpk pid_t pid, wpid; 134*45916cd2Sjpk 135*45916cd2Sjpk pid = vfork(); 136*45916cd2Sjpk switch (pid) { 137*45916cd2Sjpk case -1: 138*45916cd2Sjpk return (1); 139*45916cd2Sjpk case 0: 140*45916cd2Sjpk if (execl(MKDEVALLOC, MKDEVALLOC, DA_IS_LABELED, NULL) == -1) 141*45916cd2Sjpk exit((errno == ENOENT) ? 0 : 1); 142*45916cd2Sjpk default: 143*45916cd2Sjpk for (;;) { 144*45916cd2Sjpk wpid = waitpid(pid, &status, 0); 145*45916cd2Sjpk if (wpid == (pid_t)-1) { 146*45916cd2Sjpk if (errno == EINTR) 147*45916cd2Sjpk continue; 148*45916cd2Sjpk else 149*45916cd2Sjpk return (1); 150*45916cd2Sjpk } else { 151*45916cd2Sjpk break; 152*45916cd2Sjpk } 153*45916cd2Sjpk } 154*45916cd2Sjpk break; 155*45916cd2Sjpk } 156*45916cd2Sjpk 157*45916cd2Sjpk return ((WIFEXITED(status) == 0) ? 1 : WEXITSTATUS(status)); 158*45916cd2Sjpk } 159*45916cd2Sjpk 160*45916cd2Sjpk 161*45916cd2Sjpk /* 162*45916cd2Sjpk * _update_devalloc_db 163*45916cd2Sjpk * Forms allocatable device entries to be written to device_allocate and 164*45916cd2Sjpk * device_maps. 165*45916cd2Sjpk */ 166*45916cd2Sjpk /* ARGSUSED */ 167*45916cd2Sjpk void 168*45916cd2Sjpk _update_devalloc_db(devlist_t *devlist, int devflag, int action, char *devname, 169*45916cd2Sjpk char *root_dir) 170*45916cd2Sjpk { 171*45916cd2Sjpk int i; 172*45916cd2Sjpk deventry_t *entry = NULL, *dentry = NULL; 173*45916cd2Sjpk 174*45916cd2Sjpk if (action == DA_ADD) { 175*45916cd2Sjpk for (i = 0; i < DA_COUNT; i++) { 176*45916cd2Sjpk switch (i) { 177*45916cd2Sjpk case 0: 178*45916cd2Sjpk dentry = devlist->audio; 179*45916cd2Sjpk break; 180*45916cd2Sjpk case 1: 181*45916cd2Sjpk dentry = devlist->cd; 182*45916cd2Sjpk break; 183*45916cd2Sjpk case 2: 184*45916cd2Sjpk dentry = devlist->floppy; 185*45916cd2Sjpk break; 186*45916cd2Sjpk case 3: 187*45916cd2Sjpk dentry = devlist->tape; 188*45916cd2Sjpk break; 189*45916cd2Sjpk case 4: 190*45916cd2Sjpk dentry = devlist->rmdisk; 191*45916cd2Sjpk break; 192*45916cd2Sjpk default: 193*45916cd2Sjpk return; 194*45916cd2Sjpk } 195*45916cd2Sjpk if (dentry) 196*45916cd2Sjpk _update_dev(dentry, action, NULL); 197*45916cd2Sjpk } 198*45916cd2Sjpk } else if (action == DA_REMOVE) { 199*45916cd2Sjpk if (devflag & DA_AUDIO) 200*45916cd2Sjpk dentry = devlist->audio; 201*45916cd2Sjpk else if (devflag & DA_CD) 202*45916cd2Sjpk dentry = devlist->cd; 203*45916cd2Sjpk else if (devflag & DA_FLOPPY) 204*45916cd2Sjpk dentry = devlist->floppy; 205*45916cd2Sjpk else if (devflag & DA_TAPE) 206*45916cd2Sjpk dentry = devlist->tape; 207*45916cd2Sjpk else if (devflag & DA_RMDISK) 208*45916cd2Sjpk dentry = devlist->rmdisk; 209*45916cd2Sjpk else 210*45916cd2Sjpk return; 211*45916cd2Sjpk 212*45916cd2Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 213*45916cd2Sjpk if (strcmp(entry->devinfo.devname, devname) == 0) 214*45916cd2Sjpk break; 215*45916cd2Sjpk } 216*45916cd2Sjpk _update_dev(entry, action, devname); 217*45916cd2Sjpk } 218*45916cd2Sjpk } 219*45916cd2Sjpk 220*45916cd2Sjpk static void 221*45916cd2Sjpk _update_dev(deventry_t *dentry, int action, char *devname) 222*45916cd2Sjpk { 223*45916cd2Sjpk da_args dargs; 224*45916cd2Sjpk deventry_t newentry, *entry; 225*45916cd2Sjpk 226*45916cd2Sjpk dargs.rootdir = NULL; 227*45916cd2Sjpk dargs.devnames = NULL; 228*45916cd2Sjpk 229*45916cd2Sjpk if (action == DA_ADD) { 230*45916cd2Sjpk dargs.optflag = DA_ADD | DA_FORCE; 231*45916cd2Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 232*45916cd2Sjpk dargs.devinfo = &(entry->devinfo); 233*45916cd2Sjpk (void) da_update_device(&dargs); 234*45916cd2Sjpk } 235*45916cd2Sjpk } else if (action == DA_REMOVE) { 236*45916cd2Sjpk dargs.optflag = DA_REMOVE; 237*45916cd2Sjpk if (dentry) { 238*45916cd2Sjpk entry = dentry; 239*45916cd2Sjpk } else { 240*45916cd2Sjpk newentry.devinfo.devname = strdup(devname); 241*45916cd2Sjpk newentry.devinfo.devtype = 242*45916cd2Sjpk newentry.devinfo.devauths = 243*45916cd2Sjpk newentry.devinfo.devexec = 244*45916cd2Sjpk newentry.devinfo.devopts = 245*45916cd2Sjpk newentry.devinfo.devlist = NULL; 246*45916cd2Sjpk newentry.devinfo.instance = 0; 247*45916cd2Sjpk newentry.next = NULL; 248*45916cd2Sjpk entry = &newentry; 249*45916cd2Sjpk } 250*45916cd2Sjpk dargs.devinfo = &(entry->devinfo); 251*45916cd2Sjpk (void) da_update_device(&dargs); 252*45916cd2Sjpk } 253*45916cd2Sjpk } 254