diff options
Diffstat (limited to 'usr/src/cmd/devfsadm/devalloc.c')
| -rw-r--r-- | usr/src/cmd/devfsadm/devalloc.c | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/usr/src/cmd/devfsadm/devalloc.c b/usr/src/cmd/devfsadm/devalloc.c new file mode 100644 index 0000000000..413d617883 --- /dev/null +++ b/usr/src/cmd/devfsadm/devalloc.c @@ -0,0 +1,253 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Device allocation related work. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/dkio.h> +#include <sys/wait.h> +#include <bsm/devalloc.h> + +#define DEALLOCATE "/usr/sbin/deallocate" +#define MKDEVALLOC "/usr/sbin/mkdevalloc" + +static void _update_dev(deventry_t *, int, char *); +static int _make_db(); + + +/* + * _da_check_for_usb + * returns 1 if device pointed by 'link' is a removable hotplugged + * else returns 0. + */ +int +_da_check_for_usb(char *link, char *root_dir) +{ + int fd = -1; + int len, dstsize; + int removable = 0; + char *p = NULL; + char path[MAXPATHLEN]; + + dstsize = sizeof (path); + if (strcmp(root_dir, "") != 0) { + if (strlcat(path, root_dir, dstsize) >= dstsize) + return (0); + len = strlen(path); + } else { + len = 0; + } + if (strstr(link, "rdsk")) { + (void) snprintf(path, dstsize - len, "%s", link); + } else if (strstr(link, "dsk")) { + p = rindex(link, '/'); + if (p == NULL) + return (0); + p++; + (void) snprintf(path, dstsize - len, "%s%s", "/dev/rdsk/", p); + } else { + return (0); + } + + if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0) + return (0); + (void) ioctl(fd, DKIOCREMOVABLE, &removable); + (void) close(fd); + + return (removable); +} + +/* + * _reset_devalloc + * If device allocation is being turned on, creates device_allocate + * device_maps if they do not exist. + * Puts DEVICE_ALLOCATION=ON/OFF in device_allocate to indicate if + * device allocation is on/off. + */ +void +_reset_devalloc(int action) +{ + da_args dargs; + + if (action == DA_ON) + (void) _make_db(); + else if ((action == DA_OFF) && (open(DEVALLOC, O_RDONLY) == -1)) + return; + + if (action == DA_ON) + dargs.optflag = DA_ON; + else if (action == DA_OFF) + dargs.optflag = DA_OFF | DA_ALLOC_ONLY; + + dargs.rootdir = NULL; + dargs.devnames = NULL; + dargs.devinfo = NULL; + + (void) da_update_device(&dargs); +} + +/* + * _make_db + * execs /usr/sbin/mkdevalloc to create device_allocate and + * device_maps. + */ +static int +_make_db() +{ + int status; + pid_t pid, wpid; + + pid = vfork(); + switch (pid) { + case -1: + return (1); + case 0: + if (execl(MKDEVALLOC, MKDEVALLOC, DA_IS_LABELED, NULL) == -1) + exit((errno == ENOENT) ? 0 : 1); + default: + for (;;) { + wpid = waitpid(pid, &status, 0); + if (wpid == (pid_t)-1) { + if (errno == EINTR) + continue; + else + return (1); + } else { + break; + } + } + break; + } + + return ((WIFEXITED(status) == 0) ? 1 : WEXITSTATUS(status)); +} + + +/* + * _update_devalloc_db + * Forms allocatable device entries to be written to device_allocate and + * device_maps. + */ +/* ARGSUSED */ +void +_update_devalloc_db(devlist_t *devlist, int devflag, int action, char *devname, + char *root_dir) +{ + int i; + deventry_t *entry = NULL, *dentry = NULL; + + if (action == DA_ADD) { + for (i = 0; i < DA_COUNT; i++) { + switch (i) { + case 0: + dentry = devlist->audio; + break; + case 1: + dentry = devlist->cd; + break; + case 2: + dentry = devlist->floppy; + break; + case 3: + dentry = devlist->tape; + break; + case 4: + dentry = devlist->rmdisk; + break; + default: + return; + } + if (dentry) + _update_dev(dentry, action, NULL); + } + } else if (action == DA_REMOVE) { + if (devflag & DA_AUDIO) + dentry = devlist->audio; + else if (devflag & DA_CD) + dentry = devlist->cd; + else if (devflag & DA_FLOPPY) + dentry = devlist->floppy; + else if (devflag & DA_TAPE) + dentry = devlist->tape; + else if (devflag & DA_RMDISK) + dentry = devlist->rmdisk; + else + return; + + for (entry = dentry; entry != NULL; entry = entry->next) { + if (strcmp(entry->devinfo.devname, devname) == 0) + break; + } + _update_dev(entry, action, devname); + } +} + +static void +_update_dev(deventry_t *dentry, int action, char *devname) +{ + da_args dargs; + deventry_t newentry, *entry; + + dargs.rootdir = NULL; + dargs.devnames = NULL; + + if (action == DA_ADD) { + dargs.optflag = DA_ADD | DA_FORCE; + for (entry = dentry; entry != NULL; entry = entry->next) { + dargs.devinfo = &(entry->devinfo); + (void) da_update_device(&dargs); + } + } else if (action == DA_REMOVE) { + dargs.optflag = DA_REMOVE; + if (dentry) { + entry = dentry; + } else { + newentry.devinfo.devname = strdup(devname); + newentry.devinfo.devtype = + newentry.devinfo.devauths = + newentry.devinfo.devexec = + newentry.devinfo.devopts = + newentry.devinfo.devlist = NULL; + newentry.devinfo.instance = 0; + newentry.next = NULL; + entry = &newentry; + } + dargs.devinfo = &(entry->devinfo); + (void) da_update_device(&dargs); + } +} |
