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