11676Sjpk /* 21676Sjpk * CDDL HEADER START 31676Sjpk * 41676Sjpk * The contents of this file are subject to the terms of the 51676Sjpk * Common Development and Distribution License (the "License"). 61676Sjpk * You may not use this file except in compliance with the License. 71676Sjpk * 81676Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91676Sjpk * or http://www.opensolaris.org/os/licensing. 101676Sjpk * See the License for the specific language governing permissions 111676Sjpk * and limitations under the License. 121676Sjpk * 131676Sjpk * When distributing Covered Code, include this CDDL HEADER in each 141676Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151676Sjpk * If applicable, add the following below this CDDL HEADER, with the 161676Sjpk * fields enclosed by brackets "[]" replaced with your own identifying 171676Sjpk * information: Portions Copyright [yyyy] [name of copyright owner] 181676Sjpk * 191676Sjpk * CDDL HEADER END 201676Sjpk */ 211676Sjpk 221676Sjpk /* 23*4400Saj * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 241676Sjpk * Use is subject to license terms. 251676Sjpk */ 261676Sjpk 271676Sjpk #pragma ident "%Z%%M% %I% %E% SMI" 281676Sjpk 291676Sjpk /* 301676Sjpk * Device allocation related work. 311676Sjpk */ 321676Sjpk 331676Sjpk #include <stdio.h> 341676Sjpk #include <stdlib.h> 351676Sjpk #include <errno.h> 361676Sjpk #include <string.h> 371676Sjpk #include <strings.h> 381676Sjpk #include <unistd.h> 391676Sjpk #include <fcntl.h> 401676Sjpk #include <sys/types.h> 411676Sjpk #include <sys/stat.h> 421676Sjpk #include <sys/dkio.h> 431676Sjpk #include <sys/wait.h> 441676Sjpk #include <bsm/devalloc.h> 451676Sjpk 461676Sjpk #define DEALLOCATE "/usr/sbin/deallocate" 471676Sjpk #define MKDEVALLOC "/usr/sbin/mkdevalloc" 481676Sjpk 491676Sjpk static void _update_dev(deventry_t *, int, char *); 501676Sjpk static int _make_db(); 511676Sjpk 521676Sjpk 531676Sjpk /* 541676Sjpk * _da_check_for_usb 55*4400Saj * returns 1 if device pointed by 'link' is a removable hotplugged disk, 561676Sjpk * else returns 0. 571676Sjpk */ 581676Sjpk int 591676Sjpk _da_check_for_usb(char *link, char *root_dir) 601676Sjpk { 611676Sjpk int fd = -1; 621676Sjpk int len, dstsize; 631676Sjpk int removable = 0; 64*4400Saj int hotpluggable = 0; 651676Sjpk char *p = NULL; 66*4400Saj char path[MAXPATHLEN + 4]; 67*4400Saj char rpath[MAXPATHLEN + 4]; /* for ",raw" */ 681676Sjpk 691676Sjpk dstsize = sizeof (path); 701676Sjpk if (strcmp(root_dir, "") != 0) { 711676Sjpk if (strlcat(path, root_dir, dstsize) >= dstsize) 721676Sjpk return (0); 731676Sjpk len = strlen(path); 741676Sjpk } else { 751676Sjpk len = 0; 761676Sjpk } 77*4400Saj (void) snprintf(path, dstsize - len, "%s", link); 78*4400Saj if ((p = realpath(path, rpath)) == NULL) { 79*4400Saj p = path; 801676Sjpk } else { 81*4400Saj if (strstr(link, "rdsk")) { 82*4400Saj p = rpath; 83*4400Saj } else { 84*4400Saj (void) snprintf(path, dstsize, "%s%s", rpath, ",raw"); 85*4400Saj p = path; 86*4400Saj } 871676Sjpk } 88*4400Saj if ((fd = open(p, O_RDONLY | O_NONBLOCK)) < 0) 891676Sjpk return (0); 901676Sjpk (void) ioctl(fd, DKIOCREMOVABLE, &removable); 91*4400Saj (void) ioctl(fd, DKIOCHOTPLUGGABLE, &hotpluggable); 921676Sjpk (void) close(fd); 931676Sjpk 94*4400Saj if (removable && hotpluggable) 95*4400Saj return (1); 96*4400Saj 97*4400Saj return (0); 981676Sjpk } 991676Sjpk 1001676Sjpk /* 1011676Sjpk * _reset_devalloc 1021676Sjpk * If device allocation is being turned on, creates device_allocate 1031676Sjpk * device_maps if they do not exist. 1041676Sjpk * Puts DEVICE_ALLOCATION=ON/OFF in device_allocate to indicate if 1051676Sjpk * device allocation is on/off. 1061676Sjpk */ 1071676Sjpk void 1081676Sjpk _reset_devalloc(int action) 1091676Sjpk { 1101676Sjpk da_args dargs; 1111676Sjpk 1121676Sjpk if (action == DA_ON) 1131676Sjpk (void) _make_db(); 1141676Sjpk else if ((action == DA_OFF) && (open(DEVALLOC, O_RDONLY) == -1)) 1151676Sjpk return; 1161676Sjpk 1171676Sjpk if (action == DA_ON) 1181676Sjpk dargs.optflag = DA_ON; 1191676Sjpk else if (action == DA_OFF) 1201676Sjpk dargs.optflag = DA_OFF | DA_ALLOC_ONLY; 1211676Sjpk 1221676Sjpk dargs.rootdir = NULL; 1231676Sjpk dargs.devnames = NULL; 1241676Sjpk dargs.devinfo = NULL; 1251676Sjpk 1261676Sjpk (void) da_update_device(&dargs); 1271676Sjpk } 1281676Sjpk 1291676Sjpk /* 1301676Sjpk * _make_db 1311676Sjpk * execs /usr/sbin/mkdevalloc to create device_allocate and 1321676Sjpk * device_maps. 1331676Sjpk */ 1341676Sjpk static int 1351676Sjpk _make_db() 1361676Sjpk { 1371676Sjpk int status; 1381676Sjpk pid_t pid, wpid; 1391676Sjpk 1401676Sjpk pid = vfork(); 1411676Sjpk switch (pid) { 1421676Sjpk case -1: 1431676Sjpk return (1); 1441676Sjpk case 0: 1451676Sjpk if (execl(MKDEVALLOC, MKDEVALLOC, DA_IS_LABELED, NULL) == -1) 1461676Sjpk exit((errno == ENOENT) ? 0 : 1); 1471676Sjpk default: 1481676Sjpk for (;;) { 1491676Sjpk wpid = waitpid(pid, &status, 0); 1501676Sjpk if (wpid == (pid_t)-1) { 1511676Sjpk if (errno == EINTR) 1521676Sjpk continue; 1531676Sjpk else 1541676Sjpk return (1); 1551676Sjpk } else { 1561676Sjpk break; 1571676Sjpk } 1581676Sjpk } 1591676Sjpk break; 1601676Sjpk } 1611676Sjpk 1621676Sjpk return ((WIFEXITED(status) == 0) ? 1 : WEXITSTATUS(status)); 1631676Sjpk } 1641676Sjpk 1651676Sjpk 1661676Sjpk /* 1671676Sjpk * _update_devalloc_db 1681676Sjpk * Forms allocatable device entries to be written to device_allocate and 1691676Sjpk * device_maps. 1701676Sjpk */ 1711676Sjpk /* ARGSUSED */ 1721676Sjpk void 1731676Sjpk _update_devalloc_db(devlist_t *devlist, int devflag, int action, char *devname, 1741676Sjpk char *root_dir) 1751676Sjpk { 1761676Sjpk int i; 1771676Sjpk deventry_t *entry = NULL, *dentry = NULL; 1781676Sjpk 1791676Sjpk if (action == DA_ADD) { 1801676Sjpk for (i = 0; i < DA_COUNT; i++) { 1811676Sjpk switch (i) { 1821676Sjpk case 0: 1831676Sjpk dentry = devlist->audio; 1841676Sjpk break; 1851676Sjpk case 1: 1861676Sjpk dentry = devlist->cd; 1871676Sjpk break; 1881676Sjpk case 2: 1891676Sjpk dentry = devlist->floppy; 1901676Sjpk break; 1911676Sjpk case 3: 1921676Sjpk dentry = devlist->tape; 1931676Sjpk break; 1941676Sjpk case 4: 1951676Sjpk dentry = devlist->rmdisk; 1961676Sjpk break; 1971676Sjpk default: 1981676Sjpk return; 1991676Sjpk } 2001676Sjpk if (dentry) 2011676Sjpk _update_dev(dentry, action, NULL); 2021676Sjpk } 2031676Sjpk } else if (action == DA_REMOVE) { 2041676Sjpk if (devflag & DA_AUDIO) 2051676Sjpk dentry = devlist->audio; 2061676Sjpk else if (devflag & DA_CD) 2071676Sjpk dentry = devlist->cd; 2081676Sjpk else if (devflag & DA_FLOPPY) 2091676Sjpk dentry = devlist->floppy; 2101676Sjpk else if (devflag & DA_TAPE) 2111676Sjpk dentry = devlist->tape; 2121676Sjpk else if (devflag & DA_RMDISK) 2131676Sjpk dentry = devlist->rmdisk; 2141676Sjpk else 2151676Sjpk return; 2161676Sjpk 2171676Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 2181676Sjpk if (strcmp(entry->devinfo.devname, devname) == 0) 2191676Sjpk break; 2201676Sjpk } 2211676Sjpk _update_dev(entry, action, devname); 2221676Sjpk } 2231676Sjpk } 2241676Sjpk 2251676Sjpk static void 2261676Sjpk _update_dev(deventry_t *dentry, int action, char *devname) 2271676Sjpk { 2281676Sjpk da_args dargs; 2291676Sjpk deventry_t newentry, *entry; 2301676Sjpk 2311676Sjpk dargs.rootdir = NULL; 2321676Sjpk dargs.devnames = NULL; 2331676Sjpk 2341676Sjpk if (action == DA_ADD) { 2351676Sjpk dargs.optflag = DA_ADD | DA_FORCE; 2361676Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 2371676Sjpk dargs.devinfo = &(entry->devinfo); 2381676Sjpk (void) da_update_device(&dargs); 2391676Sjpk } 2401676Sjpk } else if (action == DA_REMOVE) { 2411676Sjpk dargs.optflag = DA_REMOVE; 2421676Sjpk if (dentry) { 2431676Sjpk entry = dentry; 2441676Sjpk } else { 2451676Sjpk newentry.devinfo.devname = strdup(devname); 2461676Sjpk newentry.devinfo.devtype = 2471676Sjpk newentry.devinfo.devauths = 2481676Sjpk newentry.devinfo.devexec = 2491676Sjpk newentry.devinfo.devopts = 2501676Sjpk newentry.devinfo.devlist = NULL; 2511676Sjpk newentry.devinfo.instance = 0; 2521676Sjpk newentry.next = NULL; 2531676Sjpk entry = &newentry; 2541676Sjpk } 2551676Sjpk dargs.devinfo = &(entry->devinfo); 2561676Sjpk (void) da_update_device(&dargs); 2571676Sjpk } 2581676Sjpk } 259