145916cd2Sjpk /* 245916cd2Sjpk * CDDL HEADER START 345916cd2Sjpk * 445916cd2Sjpk * The contents of this file are subject to the terms of the 545916cd2Sjpk * Common Development and Distribution License (the "License"). 645916cd2Sjpk * You may not use this file except in compliance with the License. 745916cd2Sjpk * 845916cd2Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 945916cd2Sjpk * or http://www.opensolaris.org/os/licensing. 1045916cd2Sjpk * See the License for the specific language governing permissions 1145916cd2Sjpk * and limitations under the License. 1245916cd2Sjpk * 1345916cd2Sjpk * When distributing Covered Code, include this CDDL HEADER in each 1445916cd2Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1545916cd2Sjpk * If applicable, add the following below this CDDL HEADER, with the 1645916cd2Sjpk * fields enclosed by brackets "[]" replaced with your own identifying 1745916cd2Sjpk * information: Portions Copyright [yyyy] [name of copyright owner] 1845916cd2Sjpk * 1945916cd2Sjpk * CDDL HEADER END 2045916cd2Sjpk */ 2145916cd2Sjpk 2245916cd2Sjpk /* 23*6e670f77Saj * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2445916cd2Sjpk * Use is subject to license terms. 2545916cd2Sjpk */ 2645916cd2Sjpk 2745916cd2Sjpk #pragma ident "%Z%%M% %I% %E% SMI" 2845916cd2Sjpk 2945916cd2Sjpk /* 3045916cd2Sjpk * Device allocation related work. 3145916cd2Sjpk */ 3245916cd2Sjpk 3345916cd2Sjpk #include <stdio.h> 3445916cd2Sjpk #include <stdlib.h> 3545916cd2Sjpk #include <errno.h> 3645916cd2Sjpk #include <string.h> 3745916cd2Sjpk #include <strings.h> 3845916cd2Sjpk #include <unistd.h> 3945916cd2Sjpk #include <fcntl.h> 4045916cd2Sjpk #include <sys/types.h> 4145916cd2Sjpk #include <sys/stat.h> 4245916cd2Sjpk #include <sys/dkio.h> 4345916cd2Sjpk #include <sys/wait.h> 4445916cd2Sjpk #include <bsm/devalloc.h> 4545916cd2Sjpk 4645916cd2Sjpk #define DEALLOCATE "/usr/sbin/deallocate" 4745916cd2Sjpk #define MKDEVALLOC "/usr/sbin/mkdevalloc" 4845916cd2Sjpk 4945916cd2Sjpk static void _update_dev(deventry_t *, int, char *); 5045916cd2Sjpk static int _make_db(); 5145916cd2Sjpk 5245916cd2Sjpk 5345916cd2Sjpk /* 5445916cd2Sjpk * _da_check_for_usb 55*6e670f77Saj * returns 1 if device pointed by 'link' is a removable hotplugged disk, 5645916cd2Sjpk * else returns 0. 5745916cd2Sjpk */ 5845916cd2Sjpk int 5945916cd2Sjpk _da_check_for_usb(char *link, char *root_dir) 6045916cd2Sjpk { 6145916cd2Sjpk int fd = -1; 6245916cd2Sjpk int len, dstsize; 6345916cd2Sjpk int removable = 0; 64*6e670f77Saj int hotpluggable = 0; 6545916cd2Sjpk char *p = NULL; 66*6e670f77Saj char path[MAXPATHLEN + 4]; 67*6e670f77Saj char rpath[MAXPATHLEN + 4]; /* for ",raw" */ 6845916cd2Sjpk 6945916cd2Sjpk dstsize = sizeof (path); 7045916cd2Sjpk if (strcmp(root_dir, "") != 0) { 7145916cd2Sjpk if (strlcat(path, root_dir, dstsize) >= dstsize) 7245916cd2Sjpk return (0); 7345916cd2Sjpk len = strlen(path); 7445916cd2Sjpk } else { 7545916cd2Sjpk len = 0; 7645916cd2Sjpk } 7745916cd2Sjpk (void) snprintf(path, dstsize - len, "%s", link); 78*6e670f77Saj if ((p = realpath(path, rpath)) == NULL) { 79*6e670f77Saj p = path; 8045916cd2Sjpk } else { 81*6e670f77Saj if (strstr(link, "rdsk")) { 82*6e670f77Saj p = rpath; 83*6e670f77Saj } else { 84*6e670f77Saj (void) snprintf(path, dstsize, "%s%s", rpath, ",raw"); 85*6e670f77Saj p = path; 8645916cd2Sjpk } 87*6e670f77Saj } 88*6e670f77Saj if ((fd = open(p, O_RDONLY | O_NONBLOCK)) < 0) 8945916cd2Sjpk return (0); 9045916cd2Sjpk (void) ioctl(fd, DKIOCREMOVABLE, &removable); 91*6e670f77Saj (void) ioctl(fd, DKIOCHOTPLUGGABLE, &hotpluggable); 9245916cd2Sjpk (void) close(fd); 9345916cd2Sjpk 94*6e670f77Saj if (removable && hotpluggable) 95*6e670f77Saj return (1); 96*6e670f77Saj 97*6e670f77Saj return (0); 9845916cd2Sjpk } 9945916cd2Sjpk 10045916cd2Sjpk /* 10145916cd2Sjpk * _reset_devalloc 10245916cd2Sjpk * If device allocation is being turned on, creates device_allocate 10345916cd2Sjpk * device_maps if they do not exist. 10445916cd2Sjpk * Puts DEVICE_ALLOCATION=ON/OFF in device_allocate to indicate if 10545916cd2Sjpk * device allocation is on/off. 10645916cd2Sjpk */ 10745916cd2Sjpk void 10845916cd2Sjpk _reset_devalloc(int action) 10945916cd2Sjpk { 11045916cd2Sjpk da_args dargs; 11145916cd2Sjpk 11245916cd2Sjpk if (action == DA_ON) 11345916cd2Sjpk (void) _make_db(); 11445916cd2Sjpk else if ((action == DA_OFF) && (open(DEVALLOC, O_RDONLY) == -1)) 11545916cd2Sjpk return; 11645916cd2Sjpk 11745916cd2Sjpk if (action == DA_ON) 11845916cd2Sjpk dargs.optflag = DA_ON; 11945916cd2Sjpk else if (action == DA_OFF) 12045916cd2Sjpk dargs.optflag = DA_OFF | DA_ALLOC_ONLY; 12145916cd2Sjpk 12245916cd2Sjpk dargs.rootdir = NULL; 12345916cd2Sjpk dargs.devnames = NULL; 12445916cd2Sjpk dargs.devinfo = NULL; 12545916cd2Sjpk 12645916cd2Sjpk (void) da_update_device(&dargs); 12745916cd2Sjpk } 12845916cd2Sjpk 12945916cd2Sjpk /* 13045916cd2Sjpk * _make_db 13145916cd2Sjpk * execs /usr/sbin/mkdevalloc to create device_allocate and 13245916cd2Sjpk * device_maps. 13345916cd2Sjpk */ 13445916cd2Sjpk static int 13545916cd2Sjpk _make_db() 13645916cd2Sjpk { 13745916cd2Sjpk int status; 13845916cd2Sjpk pid_t pid, wpid; 13945916cd2Sjpk 14045916cd2Sjpk pid = vfork(); 14145916cd2Sjpk switch (pid) { 14245916cd2Sjpk case -1: 14345916cd2Sjpk return (1); 14445916cd2Sjpk case 0: 14545916cd2Sjpk if (execl(MKDEVALLOC, MKDEVALLOC, DA_IS_LABELED, NULL) == -1) 14645916cd2Sjpk exit((errno == ENOENT) ? 0 : 1); 14745916cd2Sjpk default: 14845916cd2Sjpk for (;;) { 14945916cd2Sjpk wpid = waitpid(pid, &status, 0); 15045916cd2Sjpk if (wpid == (pid_t)-1) { 15145916cd2Sjpk if (errno == EINTR) 15245916cd2Sjpk continue; 15345916cd2Sjpk else 15445916cd2Sjpk return (1); 15545916cd2Sjpk } else { 15645916cd2Sjpk break; 15745916cd2Sjpk } 15845916cd2Sjpk } 15945916cd2Sjpk break; 16045916cd2Sjpk } 16145916cd2Sjpk 16245916cd2Sjpk return ((WIFEXITED(status) == 0) ? 1 : WEXITSTATUS(status)); 16345916cd2Sjpk } 16445916cd2Sjpk 16545916cd2Sjpk 16645916cd2Sjpk /* 16745916cd2Sjpk * _update_devalloc_db 16845916cd2Sjpk * Forms allocatable device entries to be written to device_allocate and 16945916cd2Sjpk * device_maps. 17045916cd2Sjpk */ 17145916cd2Sjpk /* ARGSUSED */ 17245916cd2Sjpk void 17345916cd2Sjpk _update_devalloc_db(devlist_t *devlist, int devflag, int action, char *devname, 17445916cd2Sjpk char *root_dir) 17545916cd2Sjpk { 17645916cd2Sjpk int i; 17745916cd2Sjpk deventry_t *entry = NULL, *dentry = NULL; 17845916cd2Sjpk 17945916cd2Sjpk if (action == DA_ADD) { 18045916cd2Sjpk for (i = 0; i < DA_COUNT; i++) { 18145916cd2Sjpk switch (i) { 18245916cd2Sjpk case 0: 18345916cd2Sjpk dentry = devlist->audio; 18445916cd2Sjpk break; 18545916cd2Sjpk case 1: 18645916cd2Sjpk dentry = devlist->cd; 18745916cd2Sjpk break; 18845916cd2Sjpk case 2: 18945916cd2Sjpk dentry = devlist->floppy; 19045916cd2Sjpk break; 19145916cd2Sjpk case 3: 19245916cd2Sjpk dentry = devlist->tape; 19345916cd2Sjpk break; 19445916cd2Sjpk case 4: 19545916cd2Sjpk dentry = devlist->rmdisk; 19645916cd2Sjpk break; 19745916cd2Sjpk default: 19845916cd2Sjpk return; 19945916cd2Sjpk } 20045916cd2Sjpk if (dentry) 20145916cd2Sjpk _update_dev(dentry, action, NULL); 20245916cd2Sjpk } 20345916cd2Sjpk } else if (action == DA_REMOVE) { 20445916cd2Sjpk if (devflag & DA_AUDIO) 20545916cd2Sjpk dentry = devlist->audio; 20645916cd2Sjpk else if (devflag & DA_CD) 20745916cd2Sjpk dentry = devlist->cd; 20845916cd2Sjpk else if (devflag & DA_FLOPPY) 20945916cd2Sjpk dentry = devlist->floppy; 21045916cd2Sjpk else if (devflag & DA_TAPE) 21145916cd2Sjpk dentry = devlist->tape; 21245916cd2Sjpk else if (devflag & DA_RMDISK) 21345916cd2Sjpk dentry = devlist->rmdisk; 21445916cd2Sjpk else 21545916cd2Sjpk return; 21645916cd2Sjpk 21745916cd2Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 21845916cd2Sjpk if (strcmp(entry->devinfo.devname, devname) == 0) 21945916cd2Sjpk break; 22045916cd2Sjpk } 22145916cd2Sjpk _update_dev(entry, action, devname); 22245916cd2Sjpk } 22345916cd2Sjpk } 22445916cd2Sjpk 22545916cd2Sjpk static void 22645916cd2Sjpk _update_dev(deventry_t *dentry, int action, char *devname) 22745916cd2Sjpk { 22845916cd2Sjpk da_args dargs; 22945916cd2Sjpk deventry_t newentry, *entry; 23045916cd2Sjpk 23145916cd2Sjpk dargs.rootdir = NULL; 23245916cd2Sjpk dargs.devnames = NULL; 23345916cd2Sjpk 23445916cd2Sjpk if (action == DA_ADD) { 23545916cd2Sjpk dargs.optflag = DA_ADD | DA_FORCE; 23645916cd2Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 23745916cd2Sjpk dargs.devinfo = &(entry->devinfo); 23845916cd2Sjpk (void) da_update_device(&dargs); 23945916cd2Sjpk } 24045916cd2Sjpk } else if (action == DA_REMOVE) { 24145916cd2Sjpk dargs.optflag = DA_REMOVE; 24245916cd2Sjpk if (dentry) { 24345916cd2Sjpk entry = dentry; 24445916cd2Sjpk } else { 24545916cd2Sjpk newentry.devinfo.devname = strdup(devname); 24645916cd2Sjpk newentry.devinfo.devtype = 24745916cd2Sjpk newentry.devinfo.devauths = 24845916cd2Sjpk newentry.devinfo.devexec = 24945916cd2Sjpk newentry.devinfo.devopts = 25045916cd2Sjpk newentry.devinfo.devlist = NULL; 25145916cd2Sjpk newentry.devinfo.instance = 0; 25245916cd2Sjpk newentry.next = NULL; 25345916cd2Sjpk entry = &newentry; 25445916cd2Sjpk } 25545916cd2Sjpk dargs.devinfo = &(entry->devinfo); 25645916cd2Sjpk (void) da_update_device(&dargs); 25745916cd2Sjpk } 25845916cd2Sjpk } 259