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 /* 2345916cd2Sjpk * Copyright 2006 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 #include <stdlib.h> 3045916cd2Sjpk #include <ctype.h> 3145916cd2Sjpk #include <unistd.h> 3245916cd2Sjpk #include <limits.h> 3345916cd2Sjpk #include <fcntl.h> 3445916cd2Sjpk #include <sys/types.h> 3545916cd2Sjpk #include <sys/stat.h> 3645916cd2Sjpk #include <utime.h> 3745916cd2Sjpk #include <synch.h> 3845916cd2Sjpk #include <strings.h> 3945916cd2Sjpk #include <string.h> 4045916cd2Sjpk #include <libintl.h> 4145916cd2Sjpk #include <errno.h> 4245916cd2Sjpk #include <auth_list.h> 4345916cd2Sjpk #include <bsm/devices.h> 4445916cd2Sjpk #include <bsm/devalloc.h> 4545916cd2Sjpk 4645916cd2Sjpk #define DA_DEFS "/etc/security/tsol/devalloc_defaults" 4745916cd2Sjpk 4845916cd2Sjpk extern int _readbufline(char *, int, char *, int, int *); 4945916cd2Sjpk extern char *strtok_r(char *, const char *, char **); 5045916cd2Sjpk extern char *_strtok_escape(char *, char *, char **); 5145916cd2Sjpk extern int getdaon(void); 5245916cd2Sjpk extern int da_matchname(devalloc_t *, char *); 5345916cd2Sjpk extern int da_match(devalloc_t *, da_args *); 5445916cd2Sjpk extern int dmap_matchname(devmap_t *, char *); 5545916cd2Sjpk extern int dm_match(devmap_t *, da_args *); 5645916cd2Sjpk 5745916cd2Sjpk /* 5845916cd2Sjpk * The following structure is for recording old entries to be retained. 5945916cd2Sjpk * We read the entries from the database into a linked list in memory, 6045916cd2Sjpk * then turn around and write them out again. 6145916cd2Sjpk */ 6245916cd2Sjpk typedef struct strentry { 6345916cd2Sjpk struct strentry *se_next; 6445916cd2Sjpk char se_str[4096 + 1]; 6545916cd2Sjpk } strentry_t; 6645916cd2Sjpk 6745916cd2Sjpk /* 6845916cd2Sjpk * da_check_longindevperm - 6945916cd2Sjpk * reads /etc/logindevperm and checks if specified device is in the file. 7045916cd2Sjpk * returns 1 if specified device found in /etc/logindevperm, else returns 0 7145916cd2Sjpk */ 7245916cd2Sjpk int 7345916cd2Sjpk da_check_logindevperm(char *devname) 7445916cd2Sjpk { 7545916cd2Sjpk int ret = 0; 7645916cd2Sjpk int fd = -1; 7745916cd2Sjpk int nlen, plen, slen, lineno, fsize; 7845916cd2Sjpk char line[MAX_CANON]; 7945916cd2Sjpk char *field_delims = " \t\n"; 8045916cd2Sjpk char *fbuf = NULL; 8145916cd2Sjpk char *ptr, *device; 8245916cd2Sjpk char *lasts = NULL; 8345916cd2Sjpk FILE *fp; 8445916cd2Sjpk struct stat f_stat; 8545916cd2Sjpk 8645916cd2Sjpk /* 8745916cd2Sjpk * check if /etc/logindevperm exists and get its size 8845916cd2Sjpk */ 8945916cd2Sjpk if ((fd = open(LOGINDEVPERM, O_RDONLY)) == -1) 9045916cd2Sjpk return (0); 9145916cd2Sjpk if (fstat(fd, &f_stat) != 0) { 9245916cd2Sjpk (void) close(fd); 9345916cd2Sjpk return (0); 9445916cd2Sjpk } 9545916cd2Sjpk fsize = f_stat.st_size; 9645916cd2Sjpk if ((fbuf = (char *)malloc(fsize)) == NULL) { 9745916cd2Sjpk (void) close(fd); 9845916cd2Sjpk return (0); 9945916cd2Sjpk } 100*004388ebScasper if ((fp = fdopen(fd, "rF")) == NULL) { 10145916cd2Sjpk free(fbuf); 10245916cd2Sjpk (void) close(fd); 10345916cd2Sjpk return (0); 10445916cd2Sjpk } 10545916cd2Sjpk 10645916cd2Sjpk /* 10745916cd2Sjpk * read and parse /etc/logindevperm 10845916cd2Sjpk */ 10945916cd2Sjpk plen = nlen = lineno = 0; 11045916cd2Sjpk while (fgets(line, MAX_CANON, fp) != NULL) { 11145916cd2Sjpk lineno++; 11245916cd2Sjpk if ((ptr = strchr(line, '#')) != NULL) 11345916cd2Sjpk *ptr = '\0'; /* handle comments */ 11445916cd2Sjpk if (strtok_r(line, field_delims, &lasts) == NULL) 11545916cd2Sjpk continue; /* ignore blank lines */ 11645916cd2Sjpk if (strtok_r(NULL, field_delims, &lasts) == NULL) 11745916cd2Sjpk /* invalid entry */ 11845916cd2Sjpk continue; 11945916cd2Sjpk if ((ptr = strtok_r(NULL, field_delims, &lasts)) == NULL) 12045916cd2Sjpk /* empty device list */ 12145916cd2Sjpk continue; 12245916cd2Sjpk nlen = strlen(ptr) + 1; /* +1 terminator */ 12345916cd2Sjpk nlen += (plen + 1); 12445916cd2Sjpk if (plen == 0) 12545916cd2Sjpk slen = snprintf(fbuf, nlen, "%s", ptr); 12645916cd2Sjpk else 12745916cd2Sjpk slen = snprintf(fbuf + plen, nlen - plen, ":%s", ptr); 12845916cd2Sjpk if (slen >= fsize) { 12945916cd2Sjpk fbuf[0] = '\0'; 13045916cd2Sjpk (void) fclose(fp); 13145916cd2Sjpk return (slen); 13245916cd2Sjpk } 13345916cd2Sjpk plen += slen; 13445916cd2Sjpk } 13545916cd2Sjpk (void) fclose(fp); 13645916cd2Sjpk 13745916cd2Sjpk /* 13845916cd2Sjpk * check if devname exists in /etc/logindevperm 13945916cd2Sjpk */ 14045916cd2Sjpk device = strtok_r(fbuf, ":", &lasts); 14145916cd2Sjpk while (device != NULL) { 14245916cd2Sjpk /* 14345916cd2Sjpk * device and devname may be one of these types - 14445916cd2Sjpk * /dev/xx 14545916cd2Sjpk * /dev/xx* 14645916cd2Sjpk * /dev/dir/xx 14745916cd2Sjpk * /dev/dir/xx* 14845916cd2Sjpk * /dev/dir/"*" 14945916cd2Sjpk */ 15045916cd2Sjpk if (strcmp(device, devname) == 0) { 15145916cd2Sjpk /* /dev/xx, /dev/dir/xx */ 15245916cd2Sjpk free(fbuf); 15345916cd2Sjpk return (1); 15445916cd2Sjpk } 15545916cd2Sjpk if ((ptr = strrchr(device, KV_WILDCHAR)) != NULL) { 15645916cd2Sjpk /* all wildcard types */ 15745916cd2Sjpk *ptr = '\0'; 15845916cd2Sjpk if (strncmp(device, devname, strlen(device)) == 0) { 15945916cd2Sjpk free(fbuf); 16045916cd2Sjpk return (1); 16145916cd2Sjpk } 16245916cd2Sjpk } 16345916cd2Sjpk device = strtok_r(NULL, ":", &lasts); 16445916cd2Sjpk } 16545916cd2Sjpk 16645916cd2Sjpk return (ret); 16745916cd2Sjpk } 16845916cd2Sjpk 16945916cd2Sjpk /* 17045916cd2Sjpk * _da_read_file - 17145916cd2Sjpk * establishes readers/writer lock on fname; reads in the file if its 17245916cd2Sjpk * contents changed since the last time we read it. 17345916cd2Sjpk * returns size of buffer read, or -1 on failure. 17445916cd2Sjpk */ 17545916cd2Sjpk int 17645916cd2Sjpk _da_read_file(char *fname, char **fbuf, time_t *ftime, rwlock_t *flock, 17745916cd2Sjpk int flag) 17845916cd2Sjpk { 17945916cd2Sjpk int fd = -1; 18045916cd2Sjpk int fsize = 0; 18145916cd2Sjpk time_t newtime; 18245916cd2Sjpk struct stat f_stat; 18345916cd2Sjpk 18445916cd2Sjpk if (flag & DA_FORCE) 18545916cd2Sjpk *ftime = 0; 18645916cd2Sjpk 18745916cd2Sjpk /* check the size and the time stamp on the file */ 18845916cd2Sjpk if (rw_rdlock(flock) != 0) 18945916cd2Sjpk return (-1); 19045916cd2Sjpk if (stat(fname, &f_stat) != 0) { 19145916cd2Sjpk (void) rw_unlock(flock); 19245916cd2Sjpk return (-1); 19345916cd2Sjpk } 19445916cd2Sjpk fsize = f_stat.st_size; 19545916cd2Sjpk newtime = f_stat.st_mtime; 19645916cd2Sjpk (void) rw_unlock(flock); 19745916cd2Sjpk 19845916cd2Sjpk while (newtime > *ftime) { 19945916cd2Sjpk /* 20045916cd2Sjpk * file has been modified since we last read it; or this 20145916cd2Sjpk * is a forced read. 20245916cd2Sjpk * read file into the buffer with rw lock. 20345916cd2Sjpk */ 20445916cd2Sjpk if (rw_wrlock(flock) != 0) 20545916cd2Sjpk return (-1); 206*004388ebScasper if ((fd = open(fname, O_RDONLY)) == -1) { 20745916cd2Sjpk (void) rw_unlock(flock); 20845916cd2Sjpk return (-1); 20945916cd2Sjpk } 21045916cd2Sjpk if (*fbuf != NULL) { 21145916cd2Sjpk free(*fbuf); 21245916cd2Sjpk *fbuf = NULL; 21345916cd2Sjpk } 21445916cd2Sjpk if ((*fbuf = malloc(fsize)) == NULL) { 21545916cd2Sjpk (void) rw_unlock(flock); 21645916cd2Sjpk (void) close(fd); 21745916cd2Sjpk return (-1); 21845916cd2Sjpk } 21945916cd2Sjpk if (read(fd, *fbuf, fsize) < fsize) { 22045916cd2Sjpk free(*fbuf); 22145916cd2Sjpk (void) rw_unlock(flock); 22245916cd2Sjpk (void) close(fd); 22345916cd2Sjpk return (-1); 22445916cd2Sjpk } 22545916cd2Sjpk (void) rw_unlock(flock); 22645916cd2Sjpk /* 22745916cd2Sjpk * verify that the file did not change just after we read it. 22845916cd2Sjpk */ 22945916cd2Sjpk if (rw_rdlock(flock) != 0) { 23045916cd2Sjpk free(*fbuf); 23145916cd2Sjpk (void) close(fd); 23245916cd2Sjpk return (-1); 23345916cd2Sjpk } 23445916cd2Sjpk if (stat(fname, &f_stat) != 0) { 23545916cd2Sjpk free(*fbuf); 23645916cd2Sjpk (void) rw_unlock(flock); 23745916cd2Sjpk (void) close(fd); 23845916cd2Sjpk return (-1); 23945916cd2Sjpk } 24045916cd2Sjpk fsize = f_stat.st_size; 24145916cd2Sjpk newtime = f_stat.st_mtime; 24245916cd2Sjpk (void) rw_unlock(flock); 24345916cd2Sjpk (void) close(fd); 24445916cd2Sjpk *ftime = newtime; 24545916cd2Sjpk } 24645916cd2Sjpk 24745916cd2Sjpk return (fsize); 24845916cd2Sjpk } 24945916cd2Sjpk 25045916cd2Sjpk /* 25145916cd2Sjpk * _update_zonename - 25245916cd2Sjpk * add/remove current zone's name to the given devalloc_t. 25345916cd2Sjpk */ 25445916cd2Sjpk void 25545916cd2Sjpk _update_zonename(da_args *dargs, devalloc_t *dap) 25645916cd2Sjpk { 25745916cd2Sjpk int i, j; 25845916cd2Sjpk int oldsize, newsize; 25945916cd2Sjpk int has_zonename = 0; 26045916cd2Sjpk char *zonename; 26145916cd2Sjpk kva_t *newkva, *oldkva; 26245916cd2Sjpk kv_t *newdata, *olddata; 26345916cd2Sjpk devinfo_t *devinfo; 26445916cd2Sjpk 26545916cd2Sjpk devinfo = dargs->devinfo; 26645916cd2Sjpk oldkva = dap->da_devopts; 26745916cd2Sjpk if (oldkva == NULL) { 26845916cd2Sjpk if (dargs->optflag & DA_REMOVE_ZONE) 26945916cd2Sjpk return; 27045916cd2Sjpk if (dargs->optflag & DA_ADD_ZONE) { 27145916cd2Sjpk newkva = _str2kva(devinfo->devopts, KV_ASSIGN, 27245916cd2Sjpk KV_TOKEN_DELIMIT); 27345916cd2Sjpk if (newkva != NULL) 27445916cd2Sjpk dap->da_devopts = newkva; 27545916cd2Sjpk return; 27645916cd2Sjpk } 27745916cd2Sjpk } 27845916cd2Sjpk newsize = oldsize = oldkva->length; 27945916cd2Sjpk if (kva_match(oldkva, DAOPT_ZONE)) 28045916cd2Sjpk has_zonename = 1; 28145916cd2Sjpk if (dargs->optflag & DA_ADD_ZONE) { 28245916cd2Sjpk if ((zonename = index(devinfo->devopts, '=')) == NULL) 28345916cd2Sjpk return; 28445916cd2Sjpk zonename++; 28545916cd2Sjpk if (has_zonename) { 28645916cd2Sjpk (void) _insert2kva(oldkva, DAOPT_ZONE, zonename); 28745916cd2Sjpk return; 28845916cd2Sjpk } 28945916cd2Sjpk newsize += 1; 29045916cd2Sjpk } else if (dargs->optflag & DA_REMOVE_ZONE) { 29145916cd2Sjpk if (has_zonename) { 29245916cd2Sjpk newsize -= 1; 29345916cd2Sjpk if (newsize == 0) { 29445916cd2Sjpk /* 29545916cd2Sjpk * If zone name was the only key/value pair, 29645916cd2Sjpk * put 'reserved' in the empty slot. 29745916cd2Sjpk */ 29845916cd2Sjpk _kva_free(oldkva); 29945916cd2Sjpk dap->da_devopts = NULL; 30045916cd2Sjpk return; 30145916cd2Sjpk } 30245916cd2Sjpk } else { 30345916cd2Sjpk return; 30445916cd2Sjpk } 30545916cd2Sjpk } 30645916cd2Sjpk newkva = _new_kva(newsize); 30745916cd2Sjpk newkva->length = 0; 30845916cd2Sjpk newdata = newkva->data; 30945916cd2Sjpk olddata = oldkva->data; 31045916cd2Sjpk for (i = 0, j = 0; i < oldsize; i++) { 31145916cd2Sjpk if ((dargs->optflag & DA_REMOVE_ZONE) && 31245916cd2Sjpk (strcmp(olddata[i].key, DAOPT_ZONE) == 0)) 31345916cd2Sjpk continue; 31445916cd2Sjpk newdata[j].key = strdup(olddata[i].key); 31545916cd2Sjpk newdata[j].value = strdup(olddata[i].value); 31645916cd2Sjpk newkva->length++; 31745916cd2Sjpk j++; 31845916cd2Sjpk } 31945916cd2Sjpk if (dargs->optflag & DA_ADD_ZONE) { 32045916cd2Sjpk newdata[j].key = strdup(DAOPT_ZONE); 32145916cd2Sjpk newdata[j].value = strdup(zonename); 32245916cd2Sjpk newkva->length++; 32345916cd2Sjpk } 32445916cd2Sjpk _kva_free(oldkva); 32545916cd2Sjpk dap->da_devopts = newkva; 32645916cd2Sjpk } 32745916cd2Sjpk 32845916cd2Sjpk /* 32945916cd2Sjpk * _dmap2str - 33045916cd2Sjpk * converts a device_map entry into a printable string 33145916cd2Sjpk * returns 0 on success, -1 on error. 33245916cd2Sjpk */ 33345916cd2Sjpk /*ARGSUSED*/ 33445916cd2Sjpk static int 33545916cd2Sjpk _dmap2str(da_args *dargs, devmap_t *dmp, char *buf, int size, const char *sep) 33645916cd2Sjpk { 33745916cd2Sjpk int length; 33845916cd2Sjpk 33945916cd2Sjpk length = snprintf(buf, size, "%s%s", dmp->dmap_devname, sep); 34045916cd2Sjpk if (length >= size) 34145916cd2Sjpk return (-1); 34245916cd2Sjpk length += snprintf(buf + length, size - length, "%s%s", 34345916cd2Sjpk dmp->dmap_devtype, sep); 34445916cd2Sjpk if (length >= size) 34545916cd2Sjpk return (-1); 34645916cd2Sjpk length += snprintf(buf + length, size - length, "%s\n", 34745916cd2Sjpk dmp->dmap_devlist); 34845916cd2Sjpk if (length >= size) 34945916cd2Sjpk return (-1); 35045916cd2Sjpk return (0); 35145916cd2Sjpk } 35245916cd2Sjpk 35345916cd2Sjpk /* 35445916cd2Sjpk * _dmap2strentry - 35545916cd2Sjpk * calls dmap2str to break given devmap_t into printable entry. 35645916cd2Sjpk * returns pointer to decoded entry, NULL on error. 35745916cd2Sjpk */ 35845916cd2Sjpk static strentry_t * 35945916cd2Sjpk _dmap2strentry(da_args *dargs, devmap_t *devmapp) 36045916cd2Sjpk { 36145916cd2Sjpk strentry_t *sep; 36245916cd2Sjpk 36345916cd2Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 36445916cd2Sjpk return (NULL); 36545916cd2Sjpk if (_dmap2str(dargs, devmapp, sep->se_str, sizeof (sep->se_str), 36645916cd2Sjpk KV_TOKEN_DELIMIT"\\\n\t") != 0) { 36745916cd2Sjpk free(sep); 36845916cd2Sjpk return (NULL); 36945916cd2Sjpk } 37045916cd2Sjpk return (sep); 37145916cd2Sjpk } 37245916cd2Sjpk 37345916cd2Sjpk /* 37445916cd2Sjpk * fix_optstr - 37545916cd2Sjpk * removes trailing ':' from buf. 37645916cd2Sjpk */ 37745916cd2Sjpk void 37845916cd2Sjpk fix_optstr(char *buf) 37945916cd2Sjpk { 38045916cd2Sjpk char *p = NULL; 38145916cd2Sjpk 38245916cd2Sjpk if (p = rindex(buf, ':')) 38345916cd2Sjpk *p = ';'; 38445916cd2Sjpk } 38545916cd2Sjpk 38645916cd2Sjpk /* 38745916cd2Sjpk * _da2str - 38845916cd2Sjpk * converts a device_allocate entry into a printable string 38945916cd2Sjpk * returns 0 on success, -1 on error. 39045916cd2Sjpk */ 39145916cd2Sjpk static int 39245916cd2Sjpk _da2str(da_args *dargs, devalloc_t *dap, char *buf, int size, const char *sep, 39345916cd2Sjpk const char *osep) 39445916cd2Sjpk { 39545916cd2Sjpk int length; 39645916cd2Sjpk int matching_entry = 0; 39745916cd2Sjpk char **dnames; 39845916cd2Sjpk 39945916cd2Sjpk if (dargs->optflag & DA_UPDATE && 40045916cd2Sjpk (dargs->optflag & DA_ADD_ZONE || 40145916cd2Sjpk dargs->optflag & DA_REMOVE_ZONE) && 40245916cd2Sjpk dargs->devnames) { 40345916cd2Sjpk for (dnames = dargs->devnames; *dnames != NULL; dnames++) { 40445916cd2Sjpk if (da_matchname(dap, *dnames)) { 40545916cd2Sjpk matching_entry = 1; 40645916cd2Sjpk break; 40745916cd2Sjpk } 40845916cd2Sjpk } 40945916cd2Sjpk } 41045916cd2Sjpk length = snprintf(buf, size, "%s%s", dap->da_devname, sep); 41145916cd2Sjpk if (length >= size) 41245916cd2Sjpk return (-1); 41345916cd2Sjpk length += snprintf(buf + length, size - length, "%s%s", 41445916cd2Sjpk dap->da_devtype, sep); 41545916cd2Sjpk if (length >= size) 41645916cd2Sjpk return (-1); 41745916cd2Sjpk if (matching_entry) 41845916cd2Sjpk _update_zonename(dargs, dap); 41945916cd2Sjpk if ((dap->da_devopts == NULL) || ((dap->da_devopts->length == 1) && 42045916cd2Sjpk (strcmp(dap->da_devopts->data->key, DA_RESERVED) == 0))) { 42145916cd2Sjpk length += snprintf(buf + length, size - length, "%s%s", 42245916cd2Sjpk DA_RESERVED, sep); 42345916cd2Sjpk } else { 42445916cd2Sjpk if (_kva2str(dap->da_devopts, buf + length, size - length, 42545916cd2Sjpk KV_ASSIGN, (char *)osep) != 0) 42645916cd2Sjpk return (-1); 42745916cd2Sjpk length = strlen(buf); 42845916cd2Sjpk } 42945916cd2Sjpk if (dap->da_devopts) 43045916cd2Sjpk fix_optstr(buf); 43145916cd2Sjpk if (length >= size) 43245916cd2Sjpk return (-1); 43345916cd2Sjpk length += snprintf(buf + length, size - length, "%s%s", 43445916cd2Sjpk DA_RESERVED, sep); 43545916cd2Sjpk if (length >= size) 43645916cd2Sjpk return (-1); 43745916cd2Sjpk length += snprintf(buf + length, size - length, "%s%s", 43845916cd2Sjpk dap->da_devauth ? dap->da_devauth : DA_ANYUSER, sep); 43945916cd2Sjpk if (length >= size) 44045916cd2Sjpk return (-1); 44145916cd2Sjpk length += snprintf(buf + length, size - length, "%s\n", 44245916cd2Sjpk dap->da_devexec ? dap->da_devexec : ""); 44345916cd2Sjpk if (length >= size) 44445916cd2Sjpk return (-1); 44545916cd2Sjpk 44645916cd2Sjpk return (0); 44745916cd2Sjpk } 44845916cd2Sjpk 44945916cd2Sjpk /* 45045916cd2Sjpk * _da2strentry - 45145916cd2Sjpk * calls da2str to break given devalloc_t into printable entry. 45245916cd2Sjpk * returns pointer to decoded entry, NULL on error. 45345916cd2Sjpk */ 45445916cd2Sjpk static strentry_t * 45545916cd2Sjpk _da2strentry(da_args *dargs, devalloc_t *dap) 45645916cd2Sjpk { 45745916cd2Sjpk strentry_t *sep; 45845916cd2Sjpk 45945916cd2Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 46045916cd2Sjpk return (NULL); 46145916cd2Sjpk if (_da2str(dargs, dap, sep->se_str, sizeof (sep->se_str), 46245916cd2Sjpk KV_DELIMITER "\\\n\t", KV_TOKEN_DELIMIT "\\\n\t") != 0) { 46345916cd2Sjpk free(sep); 46445916cd2Sjpk return (NULL); 46545916cd2Sjpk } 46645916cd2Sjpk return (sep); 46745916cd2Sjpk } 46845916cd2Sjpk 46945916cd2Sjpk /* 47045916cd2Sjpk * _def2str 47145916cd2Sjpk * converts da_defs_t into a printable string. 47245916cd2Sjpk * returns 0 on success, -1 on error. 47345916cd2Sjpk */ 47445916cd2Sjpk static int 47545916cd2Sjpk _def2str(da_defs_t *da_defs, char *buf, int size, const char *sep) 47645916cd2Sjpk { 47745916cd2Sjpk int length; 47845916cd2Sjpk 47945916cd2Sjpk length = snprintf(buf, size, "%s%s", da_defs->devtype, sep); 48045916cd2Sjpk if (length >= size) 48145916cd2Sjpk return (-1); 48245916cd2Sjpk if (da_defs->devopts) { 48345916cd2Sjpk if (_kva2str(da_defs->devopts, buf + length, size - length, 48445916cd2Sjpk KV_ASSIGN, KV_DELIMITER) != 0) 48545916cd2Sjpk return (-1); 48645916cd2Sjpk length = strlen(buf); 48745916cd2Sjpk } 48845916cd2Sjpk if (length >= size) 48945916cd2Sjpk return (-1); 49045916cd2Sjpk 49145916cd2Sjpk return (0); 49245916cd2Sjpk } 49345916cd2Sjpk 49445916cd2Sjpk /* 49545916cd2Sjpk * _def2strentry 49645916cd2Sjpk * calls _def2str to break given da_defs_t into printable entry. 49745916cd2Sjpk * returns pointer decoded entry, NULL on error. 49845916cd2Sjpk */ 49945916cd2Sjpk static strentry_t * 50045916cd2Sjpk _def2strentry(da_defs_t *da_defs) 50145916cd2Sjpk { 50245916cd2Sjpk strentry_t *sep; 50345916cd2Sjpk 50445916cd2Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 50545916cd2Sjpk return (NULL); 50645916cd2Sjpk if (_def2str(da_defs, sep->se_str, sizeof (sep->se_str), 50745916cd2Sjpk KV_TOKEN_DELIMIT) != 0) { 50845916cd2Sjpk free(sep); 50945916cd2Sjpk return (NULL); 51045916cd2Sjpk } 51145916cd2Sjpk 51245916cd2Sjpk return (sep); 51345916cd2Sjpk } 51445916cd2Sjpk 51545916cd2Sjpk /* 51645916cd2Sjpk * _build_defattrs 51745916cd2Sjpk * cycles through all defattr entries, stores them in memory. removes 51845916cd2Sjpk * entries with the given search_key (device type). 51945916cd2Sjpk * returns 0 if given entry not found, 1 if given entry removed, 2 on 52045916cd2Sjpk * error. 52145916cd2Sjpk */ 52245916cd2Sjpk static int 52345916cd2Sjpk _build_defattrs(da_args *dargs, strentry_t **head_defent) 52445916cd2Sjpk { 52545916cd2Sjpk int rc = 0; 52645916cd2Sjpk da_defs_t *da_defs; 52745916cd2Sjpk strentry_t *tail_str, *tmp_str; 52845916cd2Sjpk 52945916cd2Sjpk setdadefent(); 53045916cd2Sjpk while ((da_defs = getdadefent()) != NULL) { 53145916cd2Sjpk rc = !(strcmp(da_defs->devtype, dargs->devinfo->devtype)); 53245916cd2Sjpk if (rc && dargs->optflag & DA_ADD && 53345916cd2Sjpk !(dargs->optflag & DA_FORCE)) { 53445916cd2Sjpk /* 53545916cd2Sjpk * During DA_ADD, we keep an existing entry unless 53645916cd2Sjpk * we have DA_FORCE set to override that entry. 53745916cd2Sjpk */ 53845916cd2Sjpk dargs->optflag |= DA_NO_OVERRIDE; 53945916cd2Sjpk rc = 0; 54045916cd2Sjpk } 54145916cd2Sjpk if (rc == 0) { 54245916cd2Sjpk tmp_str = _def2strentry(da_defs); 54345916cd2Sjpk if (tmp_str == NULL) { 54445916cd2Sjpk freedadefent(da_defs); 54545916cd2Sjpk enddadefent(); 54645916cd2Sjpk return (2); 54745916cd2Sjpk } 54845916cd2Sjpk /* retaining defattr entry: tmp_str->se_str */ 54945916cd2Sjpk tmp_str->se_next = NULL; 55045916cd2Sjpk if (*head_defent == NULL) { 55145916cd2Sjpk *head_defent = tail_str = tmp_str; 55245916cd2Sjpk } else { 55345916cd2Sjpk tail_str->se_next = tmp_str; 55445916cd2Sjpk tail_str = tmp_str; 55545916cd2Sjpk } 55645916cd2Sjpk } 55745916cd2Sjpk freedadefent(da_defs); 55845916cd2Sjpk } 55945916cd2Sjpk enddadefent(); 56045916cd2Sjpk 56145916cd2Sjpk return (rc); 56245916cd2Sjpk } 56345916cd2Sjpk 56445916cd2Sjpk /* 56545916cd2Sjpk * _build_lists - 56645916cd2Sjpk * cycles through all the entries, stores them in memory. removes entries 56745916cd2Sjpk * with the given search_key (device name or type). 56845916cd2Sjpk * returns 0 if given entry not found, 1 if given entry removed, 2 on 56945916cd2Sjpk * error. 57045916cd2Sjpk */ 57145916cd2Sjpk static int 57245916cd2Sjpk _build_lists(da_args *dargs, strentry_t **head_devallocp, 57345916cd2Sjpk strentry_t **head_devmapp) 57445916cd2Sjpk { 57545916cd2Sjpk int rc = 0; 57645916cd2Sjpk devalloc_t *devallocp; 57745916cd2Sjpk devmap_t *devmapp; 57845916cd2Sjpk strentry_t *tail_str; 57945916cd2Sjpk strentry_t *tmp_str; 58045916cd2Sjpk 58145916cd2Sjpk if (dargs->optflag & DA_MAPS_ONLY) 58245916cd2Sjpk goto dmap_only; 58345916cd2Sjpk 58445916cd2Sjpk /* build device_allocate */ 58545916cd2Sjpk setdaent(); 58645916cd2Sjpk while ((devallocp = getdaent()) != NULL) { 58745916cd2Sjpk rc = da_match(devallocp, dargs); 58845916cd2Sjpk if (rc && dargs->optflag & DA_ADD && 58945916cd2Sjpk !(dargs->optflag & DA_FORCE)) { 59045916cd2Sjpk /* 59145916cd2Sjpk * During DA_ADD, we keep an existing entry unless 59245916cd2Sjpk * we have DA_FORCE set to override that entry. 59345916cd2Sjpk */ 59445916cd2Sjpk dargs->optflag |= DA_NO_OVERRIDE; 59545916cd2Sjpk rc = 0; 59645916cd2Sjpk } 59745916cd2Sjpk if (rc == 0) { 59845916cd2Sjpk tmp_str = _da2strentry(dargs, devallocp); 59945916cd2Sjpk if (tmp_str == NULL) { 60045916cd2Sjpk freedaent(devallocp); 60145916cd2Sjpk enddaent(); 60245916cd2Sjpk return (2); 60345916cd2Sjpk } 60445916cd2Sjpk /* retaining devalloc entry: tmp_str->se_str */ 60545916cd2Sjpk tmp_str->se_next = NULL; 60645916cd2Sjpk if (*head_devallocp == NULL) { 60745916cd2Sjpk *head_devallocp = tail_str = tmp_str; 60845916cd2Sjpk } else { 60945916cd2Sjpk tail_str->se_next = tmp_str; 61045916cd2Sjpk tail_str = tmp_str; 61145916cd2Sjpk } 61245916cd2Sjpk } 61345916cd2Sjpk freedaent(devallocp); 61445916cd2Sjpk } 61545916cd2Sjpk enddaent(); 61645916cd2Sjpk 61745916cd2Sjpk dmap_only: 61845916cd2Sjpk if (dargs->optflag & DA_ALLOC_ONLY) 61945916cd2Sjpk return (rc); 62045916cd2Sjpk 62145916cd2Sjpk /* build device_maps */ 62245916cd2Sjpk rc = 0; 62345916cd2Sjpk setdmapent(); 62445916cd2Sjpk while ((devmapp = getdmapent()) != NULL) { 62545916cd2Sjpk rc = dm_match(devmapp, dargs); 62645916cd2Sjpk if (rc && dargs->optflag & DA_ADD && 62745916cd2Sjpk !(dargs->optflag & DA_FORCE)) { 62845916cd2Sjpk /* 62945916cd2Sjpk * During DA_ADD, we keep an existing entry unless 63045916cd2Sjpk * we have DA_FORCE set to override that entry. 63145916cd2Sjpk */ 63245916cd2Sjpk dargs->optflag |= DA_NO_OVERRIDE; 63345916cd2Sjpk rc = 0; 63445916cd2Sjpk } 63545916cd2Sjpk if (rc == 0) { 63645916cd2Sjpk tmp_str = _dmap2strentry(dargs, devmapp); 63745916cd2Sjpk if (tmp_str == NULL) { 63845916cd2Sjpk freedmapent(devmapp); 63945916cd2Sjpk enddmapent(); 64045916cd2Sjpk return (2); 64145916cd2Sjpk } 64245916cd2Sjpk /* retaining devmap entry: tmp_str->se_str */ 64345916cd2Sjpk tmp_str->se_next = NULL; 64445916cd2Sjpk if (*head_devmapp == NULL) { 64545916cd2Sjpk *head_devmapp = tail_str = tmp_str; 64645916cd2Sjpk } else { 64745916cd2Sjpk tail_str->se_next = tmp_str; 64845916cd2Sjpk tail_str = tmp_str; 64945916cd2Sjpk } 65045916cd2Sjpk } 65145916cd2Sjpk freedmapent(devmapp); 65245916cd2Sjpk } 65345916cd2Sjpk enddmapent(); 65445916cd2Sjpk 65545916cd2Sjpk return (rc); 65645916cd2Sjpk } 65745916cd2Sjpk 65845916cd2Sjpk /* 65945916cd2Sjpk * _write_defattrs 66045916cd2Sjpk * writes current entries to devalloc_defaults. 66145916cd2Sjpk */ 66245916cd2Sjpk static void 66345916cd2Sjpk _write_defattrs(FILE *fp, strentry_t *head_defent) 66445916cd2Sjpk { 66545916cd2Sjpk strentry_t *tmp_str; 66645916cd2Sjpk 66745916cd2Sjpk for (tmp_str = head_defent; tmp_str != NULL; 66845916cd2Sjpk tmp_str = tmp_str->se_next) { 66945916cd2Sjpk (void) fputs(tmp_str->se_str, fp); 67045916cd2Sjpk (void) fputs("\n", fp); 67145916cd2Sjpk } 67245916cd2Sjpk 67345916cd2Sjpk } 67445916cd2Sjpk 67545916cd2Sjpk /* 67645916cd2Sjpk * _write_device_allocate - 67745916cd2Sjpk * writes current entries in the list to device_allocate. 67845916cd2Sjpk */ 67945916cd2Sjpk static void 68045916cd2Sjpk _write_device_allocate(char *odevalloc, FILE *dafp, strentry_t *head_devallocp) 68145916cd2Sjpk { 68245916cd2Sjpk int is_on = -1; 68345916cd2Sjpk strentry_t *tmp_str; 68445916cd2Sjpk struct stat dastat; 68545916cd2Sjpk 68645916cd2Sjpk (void) fseek(dafp, (off_t)0, SEEK_SET); 68745916cd2Sjpk 68845916cd2Sjpk /* 68945916cd2Sjpk * if the devalloc on/off string existed before, 69045916cd2Sjpk * put it back before anything else. 69145916cd2Sjpk * we need to check for the string only if the file 69245916cd2Sjpk * exists. 69345916cd2Sjpk */ 69445916cd2Sjpk if (stat(odevalloc, &dastat) == 0) { 69545916cd2Sjpk is_on = da_is_on(); 69645916cd2Sjpk if (is_on == 0) 69745916cd2Sjpk (void) fputs(DA_OFF_STR, dafp); 69845916cd2Sjpk else if (is_on == 1) 69945916cd2Sjpk (void) fputs(DA_ON_STR, dafp); 70045916cd2Sjpk } 70145916cd2Sjpk tmp_str = head_devallocp; 70245916cd2Sjpk while (tmp_str) { 70345916cd2Sjpk (void) fputs(tmp_str->se_str, dafp); 70445916cd2Sjpk (void) fputs("\n", dafp); 70545916cd2Sjpk tmp_str = tmp_str->se_next; 70645916cd2Sjpk } 70745916cd2Sjpk } 70845916cd2Sjpk 70945916cd2Sjpk /* 71045916cd2Sjpk * _write_device_maps - 71145916cd2Sjpk * writes current entries in the list to device_maps. 71245916cd2Sjpk */ 71345916cd2Sjpk static void 71445916cd2Sjpk _write_device_maps(FILE *dmfp, strentry_t *head_devmapp) 71545916cd2Sjpk { 71645916cd2Sjpk strentry_t *tmp_str; 71745916cd2Sjpk 71845916cd2Sjpk (void) fseek(dmfp, (off_t)0, SEEK_SET); 71945916cd2Sjpk 72045916cd2Sjpk tmp_str = head_devmapp; 72145916cd2Sjpk while (tmp_str) { 72245916cd2Sjpk (void) fputs(tmp_str->se_str, dmfp); 72345916cd2Sjpk (void) fputs("\n", dmfp); 72445916cd2Sjpk tmp_str = tmp_str->se_next; 72545916cd2Sjpk } 72645916cd2Sjpk } 72745916cd2Sjpk 72845916cd2Sjpk /* 72945916cd2Sjpk * _write_new_defattrs 73045916cd2Sjpk * writes the new entry to devalloc_defaults. 73145916cd2Sjpk * returns 0 on success, -1 on error. 73245916cd2Sjpk */ 73345916cd2Sjpk static int 73445916cd2Sjpk _write_new_defattrs(FILE *fp, da_args *dargs) 73545916cd2Sjpk { 73645916cd2Sjpk int count; 73745916cd2Sjpk char *tok = NULL, *tokp = NULL; 73845916cd2Sjpk char *lasts; 73945916cd2Sjpk devinfo_t *devinfo = dargs->devinfo; 74045916cd2Sjpk 74145916cd2Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 74245916cd2Sjpk return (-1); 74345916cd2Sjpk if (!devinfo->devopts) 74445916cd2Sjpk return (0); 74545916cd2Sjpk (void) fprintf(fp, "%s%s", (devinfo->devtype ? devinfo->devtype : ""), 74645916cd2Sjpk KV_TOKEN_DELIMIT); 74745916cd2Sjpk if ((tokp = (char *)malloc(strlen(devinfo->devopts))) != NULL) { 74845916cd2Sjpk (void) strcpy(tokp, devinfo->devopts); 74945916cd2Sjpk if ((tok = strtok_r(tokp, KV_DELIMITER, &lasts)) != NULL) { 75045916cd2Sjpk (void) fprintf(fp, "%s", tok); 75145916cd2Sjpk count = 1; 75245916cd2Sjpk } 75345916cd2Sjpk while ((tok = strtok_r(NULL, KV_DELIMITER, &lasts)) != NULL) { 75445916cd2Sjpk if (count) 75545916cd2Sjpk (void) fprintf(fp, "%s", KV_DELIMITER); 75645916cd2Sjpk (void) fprintf(fp, "%s", tok); 75745916cd2Sjpk count++; 75845916cd2Sjpk } 75945916cd2Sjpk } else { 76045916cd2Sjpk (void) fprintf(fp, "%s", devinfo->devopts); 76145916cd2Sjpk } 76245916cd2Sjpk 76345916cd2Sjpk return (0); 76445916cd2Sjpk } 76545916cd2Sjpk 76645916cd2Sjpk /* 76745916cd2Sjpk * _write_new_entry - 76845916cd2Sjpk * writes the new devalloc_t to device_allocate or the new devmap_t to 76945916cd2Sjpk * device_maps. 77045916cd2Sjpk * returns 0 on success, -1 on error. 77145916cd2Sjpk */ 77245916cd2Sjpk static int 77345916cd2Sjpk _write_new_entry(FILE *fp, da_args *dargs, int flag) 77445916cd2Sjpk { 77545916cd2Sjpk int count; 77645916cd2Sjpk char *tok = NULL, *tokp = NULL; 77745916cd2Sjpk char *lasts; 77845916cd2Sjpk devinfo_t *devinfo = dargs->devinfo; 77945916cd2Sjpk 78045916cd2Sjpk if (flag & DA_MAPS_ONLY) 78145916cd2Sjpk goto dmap_only; 78245916cd2Sjpk 78345916cd2Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 78445916cd2Sjpk return (-1); 78545916cd2Sjpk 78645916cd2Sjpk (void) fprintf(fp, "%s%s\\\n\t", 78745916cd2Sjpk (devinfo->devname ? devinfo->devname : ""), KV_DELIMITER); 78845916cd2Sjpk (void) fprintf(fp, "%s%s\\\n\t", 78945916cd2Sjpk (devinfo->devtype ? devinfo->devtype : ""), KV_DELIMITER); 79045916cd2Sjpk if (devinfo->devopts == NULL) { 79145916cd2Sjpk (void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED, 79245916cd2Sjpk KV_DELIMITER); 79345916cd2Sjpk } else { 79445916cd2Sjpk if ((tokp = (char *)malloc(strlen(devinfo->devopts))) != NULL) { 79545916cd2Sjpk (void) strcpy(tokp, devinfo->devopts); 79645916cd2Sjpk if ((tok = strtok_r(tokp, KV_TOKEN_DELIMIT, &lasts)) != 79745916cd2Sjpk NULL) { 79845916cd2Sjpk (void) fprintf(fp, "%s", tok); 79945916cd2Sjpk count = 1; 80045916cd2Sjpk } 80145916cd2Sjpk while ((tok = strtok_r(NULL, KV_TOKEN_DELIMIT, 80245916cd2Sjpk &lasts)) != NULL) { 80345916cd2Sjpk if (count) 80445916cd2Sjpk (void) fprintf(fp, "%s", 80545916cd2Sjpk KV_TOKEN_DELIMIT "\\\n\t"); 80645916cd2Sjpk (void) fprintf(fp, "%s", tok); 80745916cd2Sjpk count++; 80845916cd2Sjpk } 80945916cd2Sjpk if (count) 81045916cd2Sjpk (void) fprintf(fp, "%s", 81145916cd2Sjpk KV_DELIMITER "\\\n\t"); 81245916cd2Sjpk } else { 81345916cd2Sjpk (void) fprintf(fp, "%s%s", devinfo->devopts, 81445916cd2Sjpk KV_DELIMITER "\\\n\t"); 81545916cd2Sjpk } 81645916cd2Sjpk } 81745916cd2Sjpk (void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED, KV_DELIMITER); 81845916cd2Sjpk (void) fprintf(fp, "%s%s\\\n\t", 81945916cd2Sjpk (devinfo->devauths ? devinfo->devauths : DA_ANYUSER), 82045916cd2Sjpk KV_DELIMITER); 82145916cd2Sjpk (void) fprintf(fp, "%s\n", 82245916cd2Sjpk (devinfo->devexec ? devinfo->devexec : KV_DELIMITER)); 82345916cd2Sjpk 82445916cd2Sjpk dmap_only: 82545916cd2Sjpk if (flag & DA_ALLOC_ONLY) 82645916cd2Sjpk return (0); 82745916cd2Sjpk 82845916cd2Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 82945916cd2Sjpk return (-1); 83045916cd2Sjpk 83145916cd2Sjpk (void) fprintf(fp, "%s%s\\\n", 83245916cd2Sjpk (devinfo->devname ? devinfo->devname : ""), KV_TOKEN_DELIMIT); 83345916cd2Sjpk (void) fprintf(fp, "\t%s%s\\\n", 83445916cd2Sjpk (devinfo->devtype ? devinfo->devtype : ""), KV_TOKEN_DELIMIT); 83545916cd2Sjpk (void) fprintf(fp, "\t%s\n", 83645916cd2Sjpk (devinfo->devlist ? devinfo->devlist : KV_TOKEN_DELIMIT)); 83745916cd2Sjpk 83845916cd2Sjpk return (0); 83945916cd2Sjpk } 84045916cd2Sjpk 84145916cd2Sjpk /* 84245916cd2Sjpk * _da_lock_devdb - 84345916cd2Sjpk * locks the database files; lock can be either broken explicitly by 84445916cd2Sjpk * closing the fd of the lock file, or it expires automatically at process 84545916cd2Sjpk * termination. 84645916cd2Sjpk * returns fd of the lock file or -1 on error. 84745916cd2Sjpk */ 84845916cd2Sjpk int 84945916cd2Sjpk _da_lock_devdb(char *rootdir) 85045916cd2Sjpk { 85145916cd2Sjpk int lockfd = -1; 85245916cd2Sjpk char *lockfile; 85345916cd2Sjpk char path[MAXPATHLEN]; 85445916cd2Sjpk int size = sizeof (path); 85545916cd2Sjpk 85645916cd2Sjpk if (rootdir == NULL) { 85745916cd2Sjpk lockfile = DA_DB_LOCK; 85845916cd2Sjpk } else { 85945916cd2Sjpk path[0] = '\0'; 86045916cd2Sjpk if (snprintf(path, size, "%s%s", rootdir, DA_DB_LOCK) >= size) 86145916cd2Sjpk return (-1); 86245916cd2Sjpk lockfile = path; 86345916cd2Sjpk } 86445916cd2Sjpk 86545916cd2Sjpk if ((lockfd = open(lockfile, O_RDWR | O_CREAT, 0600)) == -1) 86645916cd2Sjpk /* cannot open lock file */ 86745916cd2Sjpk return (-1); 86845916cd2Sjpk 86945916cd2Sjpk (void) fchown(lockfd, DA_UID, DA_GID); 87045916cd2Sjpk 87145916cd2Sjpk if (lseek(lockfd, (off_t)0, SEEK_SET) == -1) { 87245916cd2Sjpk /* cannot position lock file */ 87345916cd2Sjpk (void) close(lockfd); 87445916cd2Sjpk return (-1); 87545916cd2Sjpk } 87645916cd2Sjpk if (lockf(lockfd, F_TLOCK, 0) == -1) { 87745916cd2Sjpk /* cannot set lock */ 87845916cd2Sjpk (void) close(lockfd); 87945916cd2Sjpk return (-1); 88045916cd2Sjpk } 88145916cd2Sjpk (void) utime(lockfile, NULL); 88245916cd2Sjpk 88345916cd2Sjpk return (lockfd); 88445916cd2Sjpk } 88545916cd2Sjpk 88645916cd2Sjpk /* 88745916cd2Sjpk * da_open_devdb - 88845916cd2Sjpk * opens one or both database files - device_allocate, device_maps - in 88945916cd2Sjpk * the specified mode. 89045916cd2Sjpk * locks the database files; lock is either broken explicitly by the 89145916cd2Sjpk * caller by closing the lock file fd, or it expires automatically at 89245916cd2Sjpk * process termination. 89345916cd2Sjpk * writes the file pointer of opened file in the input args - dafp, dmfp. 89445916cd2Sjpk * returns fd of the lock file on success, -2 if database file does not 89545916cd2Sjpk * exist, -1 on other errors. 89645916cd2Sjpk */ 89745916cd2Sjpk int 89845916cd2Sjpk da_open_devdb(char *rootdir, FILE **dafp, FILE **dmfp, int flag) 89945916cd2Sjpk { 90045916cd2Sjpk int oflag = 0; 90145916cd2Sjpk int fda = -1; 90245916cd2Sjpk int fdm = -1; 90345916cd2Sjpk int lockfd = -1; 90445916cd2Sjpk char *fname; 90545916cd2Sjpk char *fmode; 90645916cd2Sjpk char path[MAXPATHLEN]; 90745916cd2Sjpk FILE *devfile; 90845916cd2Sjpk 90945916cd2Sjpk if ((dafp == NULL) && (dmfp == NULL)) 91045916cd2Sjpk return (-1); 91145916cd2Sjpk 91245916cd2Sjpk if (flag & DA_RDWR) { 91345916cd2Sjpk oflag = DA_RDWR; 914*004388ebScasper fmode = "r+F"; 91545916cd2Sjpk } else if (flag & DA_RDONLY) { 91645916cd2Sjpk oflag = DA_RDONLY; 917*004388ebScasper fmode = "rF"; 91845916cd2Sjpk } 91945916cd2Sjpk 92045916cd2Sjpk if ((lockfd = _da_lock_devdb(rootdir)) == -1) 92145916cd2Sjpk return (-1); 92245916cd2Sjpk 92345916cd2Sjpk if ((dafp == NULL) || (flag & DA_MAPS_ONLY)) 92445916cd2Sjpk goto dmap_only; 92545916cd2Sjpk 92645916cd2Sjpk path[0] = '\0'; 92745916cd2Sjpk 92845916cd2Sjpk /* 92945916cd2Sjpk * open the device allocation file 93045916cd2Sjpk */ 93145916cd2Sjpk if (rootdir == NULL) { 93245916cd2Sjpk fname = DEVALLOC; 93345916cd2Sjpk } else { 93445916cd2Sjpk if (snprintf(path, sizeof (path), "%s%s", rootdir, 93545916cd2Sjpk DEVALLOC) >= sizeof (path)) { 93645916cd2Sjpk if (lockfd != -1) 93745916cd2Sjpk (void) close(lockfd); 93845916cd2Sjpk return (-1); 93945916cd2Sjpk } 94045916cd2Sjpk fname = path; 94145916cd2Sjpk } 94245916cd2Sjpk if ((fda = open(fname, oflag, DA_DBMODE)) == -1) { 94345916cd2Sjpk if (lockfd != -1) 94445916cd2Sjpk (void) close(lockfd); 94545916cd2Sjpk return ((errno == ENOENT) ? -2 : -1); 94645916cd2Sjpk } 94745916cd2Sjpk if ((devfile = fdopen(fda, fmode)) == NULL) { 94845916cd2Sjpk (void) close(fda); 94945916cd2Sjpk if (lockfd != -1) 95045916cd2Sjpk (void) close(lockfd); 95145916cd2Sjpk return (-1); 95245916cd2Sjpk } 95345916cd2Sjpk *dafp = devfile; 95445916cd2Sjpk (void) fchmod(fda, DA_DBMODE); 95545916cd2Sjpk 95645916cd2Sjpk if ((flag & DA_ALLOC_ONLY)) 95745916cd2Sjpk goto out; 95845916cd2Sjpk 95945916cd2Sjpk dmap_only: 96045916cd2Sjpk path[0] = '\0'; 96145916cd2Sjpk /* 96245916cd2Sjpk * open the device map file 96345916cd2Sjpk */ 96445916cd2Sjpk if (rootdir == NULL) { 96545916cd2Sjpk fname = DEVMAP; 96645916cd2Sjpk } else { 96745916cd2Sjpk if (snprintf(path, sizeof (path), "%s%s", rootdir, 96845916cd2Sjpk DEVMAP) >= sizeof (path)) { 96945916cd2Sjpk (void) close(fda); 97045916cd2Sjpk if (lockfd != -1) 97145916cd2Sjpk (void) close(lockfd); 97245916cd2Sjpk return (-1); 97345916cd2Sjpk } 97445916cd2Sjpk fname = path; 97545916cd2Sjpk } 97645916cd2Sjpk 97745916cd2Sjpk if ((fdm = open(fname, oflag, DA_DBMODE)) == -1) { 97845916cd2Sjpk if (lockfd != -1) 97945916cd2Sjpk (void) close(lockfd); 98045916cd2Sjpk return ((errno == ENOENT) ? -2 : -1); 98145916cd2Sjpk } 98245916cd2Sjpk 98345916cd2Sjpk if ((devfile = fdopen(fdm, fmode)) == NULL) { 98445916cd2Sjpk (void) close(fdm); 98545916cd2Sjpk (void) close(fda); 98645916cd2Sjpk if (lockfd != -1) 98745916cd2Sjpk (void) close(lockfd); 98845916cd2Sjpk return (-1); 98945916cd2Sjpk } 99045916cd2Sjpk *dmfp = devfile; 99145916cd2Sjpk (void) fchmod(fdm, DA_DBMODE); 99245916cd2Sjpk 99345916cd2Sjpk out: 99445916cd2Sjpk return (lockfd); 99545916cd2Sjpk } 99645916cd2Sjpk 99745916cd2Sjpk /* 99845916cd2Sjpk * _record_on_off - 99945916cd2Sjpk * adds either DA_ON_STR or DA_OFF_STR to device_allocate 100045916cd2Sjpk * returns 0 on success, -1 on error. 100145916cd2Sjpk */ 100245916cd2Sjpk static int 100345916cd2Sjpk _record_on_off(da_args *dargs, FILE *tafp, FILE *dafp) 100445916cd2Sjpk { 100545916cd2Sjpk int dafd; 100645916cd2Sjpk int nsize; 100745916cd2Sjpk int nitems = 1; 100845916cd2Sjpk int actionlen; 100945916cd2Sjpk int str_found = 0; 101045916cd2Sjpk int len = 0, nlen = 0, plen = 0; 101145916cd2Sjpk char *ptr = NULL; 101245916cd2Sjpk char *actionstr; 101345916cd2Sjpk char *nbuf = NULL; 101445916cd2Sjpk char line[MAX_CANON]; 101545916cd2Sjpk struct stat dastat; 101645916cd2Sjpk 101745916cd2Sjpk if (dargs->optflag & DA_ON) 101845916cd2Sjpk actionstr = DA_ON_STR; 101945916cd2Sjpk else 102045916cd2Sjpk actionstr = DA_OFF_STR; 102145916cd2Sjpk actionlen = strlen(actionstr); 102245916cd2Sjpk dafd = fileno(dafp); 102345916cd2Sjpk if (fstat(dafd, &dastat) == -1) 102445916cd2Sjpk return (-1); 102545916cd2Sjpk 102645916cd2Sjpk /* check the old device_allocate for on/off string */ 102745916cd2Sjpk ptr = fgets(line, MAX_CANON, dafp); 102845916cd2Sjpk if (ptr != NULL) { 102945916cd2Sjpk if ((strcmp(line, DA_ON_STR) == 0) || 103045916cd2Sjpk (strcmp(line, DA_OFF_STR) == 0)) { 103145916cd2Sjpk str_found = 1; 103245916cd2Sjpk nsize = dastat.st_size; 103345916cd2Sjpk } 103445916cd2Sjpk } 103545916cd2Sjpk if (!ptr || !str_found) { 103645916cd2Sjpk /* 103745916cd2Sjpk * the file never had either the on or the off string; 103845916cd2Sjpk * make room for it. 103945916cd2Sjpk */ 104045916cd2Sjpk str_found = 0; 104145916cd2Sjpk nsize = dastat.st_size + actionlen + 1; 104245916cd2Sjpk } 104345916cd2Sjpk if ((nbuf = (char *)malloc(nsize)) == NULL) 104445916cd2Sjpk return (-1); 104545916cd2Sjpk nbuf[0] = '\0'; 104645916cd2Sjpk /* put the on/off string */ 104745916cd2Sjpk (void) strcpy(nbuf, actionstr); 104845916cd2Sjpk nlen = strlen(nbuf); 104945916cd2Sjpk plen = nlen; 105045916cd2Sjpk if (ptr && !str_found) { 105145916cd2Sjpk /* now put the first line that we read in fgets */ 105245916cd2Sjpk nlen = plen + strlen(line) + 1; 105345916cd2Sjpk len = snprintf(nbuf + plen, nlen - plen, "%s", line); 105445916cd2Sjpk if (len >= nsize) { 105545916cd2Sjpk free(nbuf); 105645916cd2Sjpk return (-1); 105745916cd2Sjpk } 105845916cd2Sjpk plen += len; 105945916cd2Sjpk } 106045916cd2Sjpk 106145916cd2Sjpk /* now get the rest of the old file */ 106245916cd2Sjpk while (fgets(line, MAX_CANON, dafp) != NULL) { 106345916cd2Sjpk nlen = plen + strlen(line) + 1; 106445916cd2Sjpk len = snprintf(nbuf + plen, nlen - plen, "%s", line); 106545916cd2Sjpk if (len >= nsize) { 106645916cd2Sjpk free(nbuf); 106745916cd2Sjpk return (-1); 106845916cd2Sjpk } 106945916cd2Sjpk plen += len; 107045916cd2Sjpk } 107145916cd2Sjpk len = strlen(nbuf) + 1; 107245916cd2Sjpk if (len < nsize) 107345916cd2Sjpk nbuf[len] = '\n'; 107445916cd2Sjpk 107545916cd2Sjpk /* write the on/off str + the old device_allocate to the temp file */ 107645916cd2Sjpk if (fwrite(nbuf, nsize, nitems, tafp) < nitems) { 107745916cd2Sjpk free(nbuf); 107845916cd2Sjpk return (-1); 107945916cd2Sjpk } 108045916cd2Sjpk 108145916cd2Sjpk free(nbuf); 108245916cd2Sjpk 108345916cd2Sjpk return (0); 108445916cd2Sjpk } 108545916cd2Sjpk 108645916cd2Sjpk /* 108745916cd2Sjpk * da_update_defattrs - 108845916cd2Sjpk * writes default attributes to devalloc_defaults 108945916cd2Sjpk * returns 0 on success, -1 on error. 109045916cd2Sjpk */ 109145916cd2Sjpk int 109245916cd2Sjpk da_update_defattrs(da_args *dargs) 109345916cd2Sjpk { 109445916cd2Sjpk int rc = 0, lockfd = 0, tmpfd = 0; 109545916cd2Sjpk char *defpath = DEFATTRS; 109645916cd2Sjpk char *tmpdefpath = TMPATTRS; 109745916cd2Sjpk FILE *tmpfp = NULL; 109845916cd2Sjpk struct stat dstat; 109945916cd2Sjpk strentry_t *head_defent = NULL; 110045916cd2Sjpk 110145916cd2Sjpk if (dargs == NULL) 110245916cd2Sjpk return (0); 110345916cd2Sjpk if ((lockfd = _da_lock_devdb(NULL)) == -1) 110445916cd2Sjpk return (-1); 110545916cd2Sjpk if ((tmpfd = open(tmpdefpath, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 110645916cd2Sjpk (void) close(lockfd); 110745916cd2Sjpk return (-1); 110845916cd2Sjpk } 110945916cd2Sjpk (void) fchown(tmpfd, DA_UID, DA_GID); 111045916cd2Sjpk if ((tmpfp = fdopen(tmpfd, "r+")) == NULL) { 111145916cd2Sjpk (void) close(tmpfd); 111245916cd2Sjpk (void) unlink(tmpdefpath); 111345916cd2Sjpk (void) close(lockfd); 111445916cd2Sjpk return (-1); 111545916cd2Sjpk } 111645916cd2Sjpk /* 111745916cd2Sjpk * examine all entries, remove an old one if required, check 111845916cd2Sjpk * if a new one needs to be added. 111945916cd2Sjpk */ 112045916cd2Sjpk if (stat(defpath, &dstat) == 0) { 112145916cd2Sjpk if ((rc = _build_defattrs(dargs, &head_defent)) != 0) { 112245916cd2Sjpk if (rc == 1) { 112345916cd2Sjpk (void) close(tmpfd); 112445916cd2Sjpk (void) unlink(tmpdefpath); 112545916cd2Sjpk (void) close(lockfd); 112645916cd2Sjpk return (rc); 112745916cd2Sjpk } 112845916cd2Sjpk } 112945916cd2Sjpk } 113045916cd2Sjpk /* 113145916cd2Sjpk * write back any existing entries. 113245916cd2Sjpk */ 113345916cd2Sjpk _write_defattrs(tmpfp, head_defent); 113445916cd2Sjpk 113545916cd2Sjpk if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) { 113645916cd2Sjpk /* add new entries */ 113745916cd2Sjpk rc = _write_new_defattrs(tmpfp, dargs); 113845916cd2Sjpk (void) fclose(tmpfp); 113945916cd2Sjpk } else { 114045916cd2Sjpk (void) fclose(tmpfp); 114145916cd2Sjpk } 114245916cd2Sjpk if (rename(tmpdefpath, defpath) != 0) { 114345916cd2Sjpk rc = -1; 114445916cd2Sjpk (void) unlink(tmpdefpath); 114545916cd2Sjpk } 114645916cd2Sjpk (void) close(lockfd); 114745916cd2Sjpk 114845916cd2Sjpk return (rc); 114945916cd2Sjpk } 115045916cd2Sjpk 115145916cd2Sjpk /* 115245916cd2Sjpk * da_update_device - 115345916cd2Sjpk * writes devices entries to device_allocate and device_maps. 115445916cd2Sjpk * returns 0 on success, -1 on error. 115545916cd2Sjpk */ 115645916cd2Sjpk int 115745916cd2Sjpk da_update_device(da_args *dargs) 115845916cd2Sjpk { 115945916cd2Sjpk int rc; 116045916cd2Sjpk int tafd = -1, tmfd = -1; 116145916cd2Sjpk int lockfd = -1; 116245916cd2Sjpk char *rootdir = NULL; 116345916cd2Sjpk char *apathp = NULL, *mpathp = NULL, *dapathp = NULL, 116445916cd2Sjpk *dmpathp = NULL; 116545916cd2Sjpk char apath[MAXPATHLEN], mpath[MAXPATHLEN], 116645916cd2Sjpk dapath[MAXPATHLEN], dmpath[MAXPATHLEN]; 116745916cd2Sjpk FILE *tafp = NULL, *tmfp = NULL, *dafp = NULL; 116845916cd2Sjpk struct stat dastat; 116945916cd2Sjpk devinfo_t *devinfo; 117045916cd2Sjpk strentry_t *head_devmapp = NULL; 117145916cd2Sjpk strentry_t *head_devallocp = NULL; 117245916cd2Sjpk 117345916cd2Sjpk if (dargs == NULL) 117445916cd2Sjpk return (0); 117545916cd2Sjpk 117645916cd2Sjpk rootdir = dargs->rootdir; 117745916cd2Sjpk devinfo = dargs->devinfo; 117845916cd2Sjpk 117945916cd2Sjpk /* 118045916cd2Sjpk * adding/removing entries should be done in both 118145916cd2Sjpk * device_allocate and device_maps. updates can be 118245916cd2Sjpk * done in both or either of the files. 118345916cd2Sjpk */ 118445916cd2Sjpk if (dargs->optflag & DA_ADD || dargs->optflag & DA_REMOVE) { 118545916cd2Sjpk if (dargs->optflag & DA_ALLOC_ONLY || 118645916cd2Sjpk dargs->optflag & DA_MAPS_ONLY) 118745916cd2Sjpk return (0); 118845916cd2Sjpk } 118945916cd2Sjpk 119045916cd2Sjpk /* 119145916cd2Sjpk * name, type and list are required fields for adding a new 119245916cd2Sjpk * device. 119345916cd2Sjpk */ 119445916cd2Sjpk if ((dargs->optflag & DA_ADD) && 119545916cd2Sjpk ((devinfo->devname == NULL) || 119645916cd2Sjpk (devinfo->devtype == NULL) || 119745916cd2Sjpk (devinfo->devlist == NULL))) { 119845916cd2Sjpk return (-1); 119945916cd2Sjpk } 120045916cd2Sjpk 120145916cd2Sjpk if (rootdir != NULL) { 120245916cd2Sjpk if (snprintf(apath, sizeof (apath), "%s%s", rootdir, 120345916cd2Sjpk TMPALLOC) >= sizeof (apath)) 120445916cd2Sjpk return (-1); 120545916cd2Sjpk apathp = apath; 120645916cd2Sjpk if (snprintf(dapath, sizeof (dapath), "%s%s", rootdir, 120745916cd2Sjpk DEVALLOC) >= sizeof (dapath)) 120845916cd2Sjpk return (-1); 120945916cd2Sjpk dapathp = dapath; 121045916cd2Sjpk if (!(dargs->optflag & DA_ALLOC_ONLY)) { 121145916cd2Sjpk if (snprintf(mpath, sizeof (mpath), "%s%s", rootdir, 121245916cd2Sjpk TMPMAP) >= sizeof (mpath)) 121345916cd2Sjpk return (-1); 121445916cd2Sjpk mpathp = mpath; 121545916cd2Sjpk if (snprintf(dmpath, sizeof (dmpath), "%s%s", rootdir, 121645916cd2Sjpk DEVMAP) >= sizeof (dmpath)) 121745916cd2Sjpk return (-1); 121845916cd2Sjpk dmpathp = dmpath; 121945916cd2Sjpk } 122045916cd2Sjpk } else { 122145916cd2Sjpk apathp = TMPALLOC; 122245916cd2Sjpk dapathp = DEVALLOC; 122345916cd2Sjpk mpathp = TMPMAP; 122445916cd2Sjpk dmpathp = DEVMAP; 122545916cd2Sjpk } 122645916cd2Sjpk 122745916cd2Sjpk if (dargs->optflag & DA_MAPS_ONLY) 122845916cd2Sjpk goto dmap_only; 122945916cd2Sjpk 123045916cd2Sjpk /* 123145916cd2Sjpk * Check if we are here just to record on/off status of 123245916cd2Sjpk * device_allocation. 123345916cd2Sjpk */ 123445916cd2Sjpk if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) 123545916cd2Sjpk lockfd = da_open_devdb(dargs->rootdir, &dafp, NULL, 123645916cd2Sjpk DA_RDONLY|DA_ALLOC_ONLY); 123745916cd2Sjpk else 123845916cd2Sjpk lockfd = _da_lock_devdb(rootdir); 123945916cd2Sjpk if (lockfd == -1) 124045916cd2Sjpk return (-1); 124145916cd2Sjpk 124245916cd2Sjpk if ((tafd = open(apathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 124345916cd2Sjpk (void) close(lockfd); 124445916cd2Sjpk (void) fclose(dafp); 124545916cd2Sjpk return (-1); 124645916cd2Sjpk } 124745916cd2Sjpk (void) fchown(tafd, DA_UID, DA_GID); 124845916cd2Sjpk if ((tafp = fdopen(tafd, "r+")) == NULL) { 124945916cd2Sjpk (void) close(tafd); 125045916cd2Sjpk (void) unlink(apathp); 125145916cd2Sjpk (void) fclose(dafp); 125245916cd2Sjpk (void) close(lockfd); 125345916cd2Sjpk return (-1); 125445916cd2Sjpk } 125545916cd2Sjpk 125645916cd2Sjpk /* 125745916cd2Sjpk * We don't need to parse the file if we are here just to record 125845916cd2Sjpk * on/off status of device_allocation. 125945916cd2Sjpk */ 126045916cd2Sjpk if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) { 126145916cd2Sjpk if (_record_on_off(dargs, tafp, dafp) == -1) { 126245916cd2Sjpk (void) close(tafd); 126345916cd2Sjpk (void) unlink(apathp); 126445916cd2Sjpk (void) fclose(dafp); 126545916cd2Sjpk (void) close(lockfd); 126645916cd2Sjpk return (-1); 126745916cd2Sjpk } 126845916cd2Sjpk (void) fclose(dafp); 126945916cd2Sjpk goto out; 127045916cd2Sjpk } 127145916cd2Sjpk 127245916cd2Sjpk /* 127345916cd2Sjpk * examine all the entries, remove an old one if forced to, 127445916cd2Sjpk * and check that they are suitable for updating. 127545916cd2Sjpk * we need to do this only if the file exists already. 127645916cd2Sjpk */ 127745916cd2Sjpk if (stat(dapathp, &dastat) == 0) { 127845916cd2Sjpk if ((rc = _build_lists(dargs, &head_devallocp, 127945916cd2Sjpk &head_devmapp)) != 0) { 128045916cd2Sjpk if (rc != 1) { 128145916cd2Sjpk (void) close(tafd); 128245916cd2Sjpk (void) unlink(apathp); 128345916cd2Sjpk (void) close(lockfd); 128445916cd2Sjpk return (rc); 128545916cd2Sjpk } 128645916cd2Sjpk } 128745916cd2Sjpk } 128845916cd2Sjpk 128945916cd2Sjpk /* 129045916cd2Sjpk * write back any existing devalloc entries, along with 129145916cd2Sjpk * the devalloc on/off string. 129245916cd2Sjpk */ 129345916cd2Sjpk _write_device_allocate(dapathp, tafp, head_devallocp); 129445916cd2Sjpk 129545916cd2Sjpk if (dargs->optflag & DA_ALLOC_ONLY) 129645916cd2Sjpk goto out; 129745916cd2Sjpk 129845916cd2Sjpk dmap_only: 129945916cd2Sjpk if ((tmfd = open(mpathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 130045916cd2Sjpk (void) close(tafd); 130145916cd2Sjpk (void) unlink(apathp); 130245916cd2Sjpk (void) close(lockfd); 130345916cd2Sjpk return (-1); 130445916cd2Sjpk } 130545916cd2Sjpk (void) fchown(tmfd, DA_UID, DA_GID); 130645916cd2Sjpk if ((tmfp = fdopen(tmfd, "r+")) == NULL) { 130745916cd2Sjpk (void) close(tafd); 130845916cd2Sjpk (void) unlink(apathp); 130945916cd2Sjpk (void) close(tmfd); 131045916cd2Sjpk (void) unlink(mpathp); 131145916cd2Sjpk (void) close(lockfd); 131245916cd2Sjpk return (-1); 131345916cd2Sjpk } 131445916cd2Sjpk 131545916cd2Sjpk /* write back any existing devmap entries */ 131645916cd2Sjpk if (head_devmapp != NULL) 131745916cd2Sjpk _write_device_maps(tmfp, head_devmapp); 131845916cd2Sjpk 131945916cd2Sjpk out: 132045916cd2Sjpk if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) { 132145916cd2Sjpk /* add any new entries */ 132245916cd2Sjpk rc = _write_new_entry(tafp, dargs, DA_ALLOC_ONLY); 132345916cd2Sjpk (void) fclose(tafp); 132445916cd2Sjpk 132545916cd2Sjpk if (rc == 0) 132645916cd2Sjpk rc = _write_new_entry(tmfp, dargs, DA_MAPS_ONLY); 132745916cd2Sjpk (void) fclose(tmfp); 132845916cd2Sjpk } else { 132945916cd2Sjpk if (tafp) 133045916cd2Sjpk (void) fclose(tafp); 133145916cd2Sjpk if (tmfp) 133245916cd2Sjpk (void) fclose(tmfp); 133345916cd2Sjpk } 133445916cd2Sjpk 133545916cd2Sjpk rc = 0; 133645916cd2Sjpk if (!(dargs->optflag & DA_MAPS_ONLY)) { 133745916cd2Sjpk if (rename(apathp, dapathp) != 0) { 133845916cd2Sjpk rc = -1; 133945916cd2Sjpk (void) unlink(apathp); 134045916cd2Sjpk } 134145916cd2Sjpk } 134245916cd2Sjpk if (!(dargs->optflag & DA_ALLOC_ONLY)) { 134345916cd2Sjpk if (rename(mpathp, dmpathp) != 0) { 134445916cd2Sjpk rc = -1; 134545916cd2Sjpk (void) unlink(mpathp); 134645916cd2Sjpk } 134745916cd2Sjpk } 134845916cd2Sjpk 134945916cd2Sjpk (void) close(lockfd); 135045916cd2Sjpk 135145916cd2Sjpk return (rc); 135245916cd2Sjpk } 135345916cd2Sjpk 135445916cd2Sjpk /* 135545916cd2Sjpk * da_add_list - 135645916cd2Sjpk * adds new /dev link name to the linked list of devices. 135745916cd2Sjpk * returns 0 if link added successfully, -1 on error. 135845916cd2Sjpk */ 135945916cd2Sjpk int 136045916cd2Sjpk da_add_list(devlist_t *dlist, char *link, int new_instance, int flag) 136145916cd2Sjpk { 136245916cd2Sjpk int instance; 136345916cd2Sjpk int nlen, plen; 136445916cd2Sjpk int new_entry = 0; 136545916cd2Sjpk char *dtype, *dexec, *tname, *kval; 136645916cd2Sjpk char *minstr = NULL, *maxstr = NULL; 136745916cd2Sjpk char dname[DA_MAXNAME]; 136845916cd2Sjpk kva_t *kva; 136945916cd2Sjpk deventry_t *dentry = NULL, *nentry = NULL, *pentry = NULL; 137045916cd2Sjpk da_defs_t *da_defs; 137145916cd2Sjpk 137245916cd2Sjpk if (dlist == NULL || link == NULL) 137345916cd2Sjpk return (-1); 137445916cd2Sjpk 137545916cd2Sjpk dname[0] = '\0'; 137645916cd2Sjpk if (flag & DA_AUDIO) { 137745916cd2Sjpk dentry = dlist->audio; 137845916cd2Sjpk tname = DA_AUDIO_NAME; 137945916cd2Sjpk dtype = DA_AUDIO_TYPE; 138045916cd2Sjpk dexec = DA_DEFAULT_AUDIO_CLEAN; 138145916cd2Sjpk } else if (flag & DA_CD) { 138245916cd2Sjpk dentry = dlist->cd; 138345916cd2Sjpk tname = DA_CD_NAME; 138445916cd2Sjpk dtype = DA_CD_TYPE; 138545916cd2Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 138645916cd2Sjpk } else if (flag & DA_FLOPPY) { 138745916cd2Sjpk dentry = dlist->floppy; 138845916cd2Sjpk tname = DA_FLOPPY_NAME; 138945916cd2Sjpk dtype = DA_FLOPPY_TYPE; 139045916cd2Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 139145916cd2Sjpk } else if (flag & DA_TAPE) { 139245916cd2Sjpk dentry = dlist->tape; 139345916cd2Sjpk tname = DA_TAPE_NAME; 139445916cd2Sjpk dtype = DA_TAPE_TYPE; 139545916cd2Sjpk dexec = DA_DEFAULT_TAPE_CLEAN; 139645916cd2Sjpk } else if (flag & DA_RMDISK) { 139745916cd2Sjpk dentry = dlist->rmdisk; 139845916cd2Sjpk tname = DA_RMDISK_NAME; 139945916cd2Sjpk dtype = DA_RMDISK_TYPE; 140045916cd2Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 140145916cd2Sjpk } else { 140245916cd2Sjpk return (-1); 140345916cd2Sjpk } 140445916cd2Sjpk 140545916cd2Sjpk for (nentry = dentry; nentry != NULL; nentry = nentry->next) { 140645916cd2Sjpk pentry = nentry; 140745916cd2Sjpk (void) sscanf(nentry->devinfo.devname, "%*[a-z]%d", &instance); 140845916cd2Sjpk if (nentry->devinfo.instance == new_instance) 140945916cd2Sjpk /* 141045916cd2Sjpk * Add the new link name to the list of links 141145916cd2Sjpk * that the device 'dname' has. 141245916cd2Sjpk */ 141345916cd2Sjpk break; 141445916cd2Sjpk } 141545916cd2Sjpk 141645916cd2Sjpk if (nentry == NULL) { 141745916cd2Sjpk /* 141845916cd2Sjpk * Either this is the first entry ever, or no matching entry 141945916cd2Sjpk * was found. Create a new one and add to the list. 142045916cd2Sjpk */ 142145916cd2Sjpk if (dentry == NULL) /* first entry ever */ 142245916cd2Sjpk instance = 0; 142345916cd2Sjpk else /* no matching entry */ 142445916cd2Sjpk instance++; 142545916cd2Sjpk (void) snprintf(dname, sizeof (dname), "%s%d", tname, instance); 142645916cd2Sjpk if ((nentry = (deventry_t *)malloc(sizeof (deventry_t))) == 142745916cd2Sjpk NULL) 142845916cd2Sjpk return (-1); 142945916cd2Sjpk if (pentry != NULL) 143045916cd2Sjpk pentry->next = nentry; 143145916cd2Sjpk new_entry = 1; 143245916cd2Sjpk nentry->devinfo.devname = strdup(dname); 143345916cd2Sjpk nentry->devinfo.devtype = dtype; 143445916cd2Sjpk nentry->devinfo.devauths = DEFAULT_DEV_ALLOC_AUTH; 143545916cd2Sjpk nentry->devinfo.devexec = dexec; 143645916cd2Sjpk nentry->devinfo.instance = new_instance; 143745916cd2Sjpk /* 143845916cd2Sjpk * Look for default label range, authorizations and cleaning 143945916cd2Sjpk * program in devalloc_defaults. If label range is not 144045916cd2Sjpk * specified in devalloc_defaults, assume it to be admin_low 144145916cd2Sjpk * to admin_high. 144245916cd2Sjpk */ 144345916cd2Sjpk minstr = DA_DEFAULT_MIN; 144445916cd2Sjpk maxstr = DA_DEFAULT_MAX; 144545916cd2Sjpk setdadefent(); 144645916cd2Sjpk if (da_defs = getdadeftype(nentry->devinfo.devtype)) { 144745916cd2Sjpk kva = da_defs->devopts; 144845916cd2Sjpk if ((kval = kva_match(kva, DAOPT_MINLABEL)) != NULL) 144945916cd2Sjpk minstr = strdup(kval); 145045916cd2Sjpk if ((kval = kva_match(kva, DAOPT_MAXLABEL)) != NULL) 145145916cd2Sjpk maxstr = strdup(kval); 145245916cd2Sjpk if ((kval = kva_match(kva, DAOPT_AUTHS)) != NULL) 145345916cd2Sjpk nentry->devinfo.devauths = strdup(kval); 145445916cd2Sjpk if ((kval = kva_match(kva, DAOPT_CSCRIPT)) != NULL) 145545916cd2Sjpk nentry->devinfo.devexec = strdup(kval); 145645916cd2Sjpk freedadefent(da_defs); 145745916cd2Sjpk } 145845916cd2Sjpk enddadefent(); 145945916cd2Sjpk kval = NULL; 146045916cd2Sjpk nlen = strlen(DAOPT_MINLABEL) + strlen(KV_ASSIGN) + 146145916cd2Sjpk strlen(minstr) + strlen(KV_TOKEN_DELIMIT) + 146245916cd2Sjpk strlen(DAOPT_MAXLABEL) + strlen(KV_ASSIGN) + strlen(maxstr) 146345916cd2Sjpk + 1; /* +1 for terminator */ 146445916cd2Sjpk if (kval = (char *)malloc(nlen)) 146545916cd2Sjpk (void) snprintf(kval, nlen, "%s%s%s%s%s%s%s", 146645916cd2Sjpk DAOPT_MINLABEL, KV_ASSIGN, minstr, KV_TOKEN_DELIMIT, 146745916cd2Sjpk DAOPT_MAXLABEL, KV_ASSIGN, maxstr); 146845916cd2Sjpk nentry->devinfo.devopts = kval; 146945916cd2Sjpk 147045916cd2Sjpk nentry->devinfo.devlist = NULL; 147145916cd2Sjpk nentry->next = NULL; 147245916cd2Sjpk } 147345916cd2Sjpk 147445916cd2Sjpk nlen = strlen(link) + 1; /* +1 terminator */ 147545916cd2Sjpk if (nentry->devinfo.devlist) { 147645916cd2Sjpk plen = strlen(nentry->devinfo.devlist); 147745916cd2Sjpk nlen = nlen + plen + 1; /* +1 for blank to separate entries */ 147845916cd2Sjpk } else { 147945916cd2Sjpk plen = 0; 148045916cd2Sjpk } 148145916cd2Sjpk 148245916cd2Sjpk if ((nentry->devinfo.devlist = 148345916cd2Sjpk (char *)realloc(nentry->devinfo.devlist, nlen)) == NULL) { 148445916cd2Sjpk if (new_entry) { 148545916cd2Sjpk nentry->devinfo.devname = NULL; 148645916cd2Sjpk free(nentry->devinfo.devname); 148745916cd2Sjpk nentry = NULL; 148845916cd2Sjpk free(nentry); 148945916cd2Sjpk if (pentry != NULL) 149045916cd2Sjpk pentry->next = NULL; 149145916cd2Sjpk } 149245916cd2Sjpk return (-1); 149345916cd2Sjpk } 149445916cd2Sjpk 149545916cd2Sjpk if (plen == 0) 149645916cd2Sjpk (void) snprintf(nentry->devinfo.devlist, nlen, "%s", link); 149745916cd2Sjpk else 149845916cd2Sjpk (void) snprintf(nentry->devinfo.devlist + plen, nlen - plen, 149945916cd2Sjpk " %s", link); 150045916cd2Sjpk 150145916cd2Sjpk if (pentry == NULL) { 150245916cd2Sjpk /* 150345916cd2Sjpk * This is the first entry of this device type. 150445916cd2Sjpk */ 150545916cd2Sjpk if (flag & DA_AUDIO) 150645916cd2Sjpk dlist->audio = nentry; 150745916cd2Sjpk else if (flag & DA_CD) 150845916cd2Sjpk dlist->cd = nentry; 150945916cd2Sjpk else if (flag & DA_FLOPPY) 151045916cd2Sjpk dlist->floppy = nentry; 151145916cd2Sjpk else if (flag & DA_TAPE) 151245916cd2Sjpk dlist->tape = nentry; 151345916cd2Sjpk else if (flag & DA_RMDISK) 151445916cd2Sjpk dlist->rmdisk = nentry; 151545916cd2Sjpk } 151645916cd2Sjpk 151745916cd2Sjpk return (0); 151845916cd2Sjpk } 151945916cd2Sjpk 152045916cd2Sjpk /* 152145916cd2Sjpk * da_remove_list - 152245916cd2Sjpk * removes a /dev link name from the linked list of devices. 152345916cd2Sjpk * returns type of device if link for that device removed 152445916cd2Sjpk * successfully, else returns -1 on error. 152545916cd2Sjpk * if all links for a device are removed, stores that device 152645916cd2Sjpk * name in devname. 152745916cd2Sjpk */ 152845916cd2Sjpk int 152945916cd2Sjpk da_remove_list(devlist_t *dlist, char *link, int type, char *devname, int size) 153045916cd2Sjpk { 153145916cd2Sjpk int flag; 153245916cd2Sjpk int remove_dev = 0; 153345916cd2Sjpk int nlen, plen, slen; 153445916cd2Sjpk char *lasts, *lname, *oldlist; 153545916cd2Sjpk struct stat rmstat; 153645916cd2Sjpk deventry_t *dentry, *current, *prev; 153745916cd2Sjpk 153845916cd2Sjpk if (type != NULL) 153945916cd2Sjpk flag = type; 154045916cd2Sjpk else if (link == NULL) 154145916cd2Sjpk return (-1); 154245916cd2Sjpk else if (strstr(link, DA_AUDIO_NAME) || strstr(link, DA_SOUND_NAME)) 154345916cd2Sjpk flag = DA_AUDIO; 154445916cd2Sjpk else if (strstr(link, "dsk") || strstr(link, "rdsk") || 154545916cd2Sjpk strstr(link, "sr") || strstr(link, "rsr")) 154645916cd2Sjpk flag = DA_CD; 154745916cd2Sjpk else if (strstr(link, "fd") || strstr(link, "rfd") || 154845916cd2Sjpk strstr(link, "diskette") || strstr(link, "rdiskette")) 154945916cd2Sjpk flag = DA_FLOPPY; 155045916cd2Sjpk else if (strstr(link, DA_TAPE_NAME)) 155145916cd2Sjpk flag = DA_TAPE; 155245916cd2Sjpk else 155345916cd2Sjpk flag = DA_RMDISK; 155445916cd2Sjpk 155545916cd2Sjpk switch (type) { 155645916cd2Sjpk case DA_AUDIO: 155745916cd2Sjpk dentry = dlist->audio; 155845916cd2Sjpk break; 155945916cd2Sjpk case DA_CD: 156045916cd2Sjpk dentry = dlist->cd; 156145916cd2Sjpk break; 156245916cd2Sjpk case DA_FLOPPY: 156345916cd2Sjpk dentry = dlist->floppy; 156445916cd2Sjpk break; 156545916cd2Sjpk case DA_TAPE: 156645916cd2Sjpk dentry = dlist->tape; 156745916cd2Sjpk break; 156845916cd2Sjpk case DA_RMDISK: 156945916cd2Sjpk dentry = dlist->rmdisk; 157045916cd2Sjpk break; 157145916cd2Sjpk default: 157245916cd2Sjpk return (-1); 157345916cd2Sjpk } 157445916cd2Sjpk 157545916cd2Sjpk if ((type != NULL) && (link == NULL)) { 157645916cd2Sjpk for (current = dentry, prev = dentry; current != NULL; 157745916cd2Sjpk current = current->next) { 157845916cd2Sjpk oldlist = strdup(current->devinfo.devlist); 157945916cd2Sjpk for (lname = strtok_r(oldlist, " ", &lasts); 158045916cd2Sjpk lname != NULL; 158145916cd2Sjpk lname = strtok_r(NULL, " ", &lasts)) { 158245916cd2Sjpk if (stat(lname, &rmstat) != 0) { 158345916cd2Sjpk remove_dev = 1; 158445916cd2Sjpk goto remove_dev; 158545916cd2Sjpk } 158645916cd2Sjpk } 158745916cd2Sjpk prev = current; 158845916cd2Sjpk } 158945916cd2Sjpk return (-1); 159045916cd2Sjpk } 159145916cd2Sjpk 159245916cd2Sjpk for (current = dentry, prev = dentry; current != NULL; 159345916cd2Sjpk current = current->next) { 159445916cd2Sjpk plen = strlen(current->devinfo.devlist); 159545916cd2Sjpk nlen = strlen(link); 159645916cd2Sjpk if (plen == nlen) { 159745916cd2Sjpk if (strcmp(current->devinfo.devlist, link) == 0) { 159845916cd2Sjpk /* last name in the list */ 159945916cd2Sjpk remove_dev = 1; 160045916cd2Sjpk break; 160145916cd2Sjpk } 160245916cd2Sjpk } 160345916cd2Sjpk if (strstr(current->devinfo.devlist, link)) { 160445916cd2Sjpk nlen = plen - nlen + 1; 160545916cd2Sjpk oldlist = strdup(current->devinfo.devlist); 160645916cd2Sjpk if ((current->devinfo.devlist = 160745916cd2Sjpk (char *)realloc(current->devinfo.devlist, 160845916cd2Sjpk nlen)) == NULL) { 160945916cd2Sjpk free(oldlist); 161045916cd2Sjpk return (-1); 161145916cd2Sjpk } 161245916cd2Sjpk current->devinfo.devlist[0] = '\0'; 161345916cd2Sjpk nlen = plen = slen = 0; 161445916cd2Sjpk for (lname = strtok_r(oldlist, " ", &lasts); 161545916cd2Sjpk lname != NULL; 161645916cd2Sjpk lname = strtok_r(NULL, " ", &lasts)) { 161745916cd2Sjpk if (strcmp(lname, link) == 0) 161845916cd2Sjpk continue; 161945916cd2Sjpk nlen = strlen(lname) + plen + 1; 162045916cd2Sjpk if (plen == 0) { 162145916cd2Sjpk slen = 162245916cd2Sjpk snprintf(current->devinfo.devlist, 162345916cd2Sjpk nlen, "%s", lname); 162445916cd2Sjpk } else { 162545916cd2Sjpk slen = 162645916cd2Sjpk snprintf(current->devinfo.devlist + 162745916cd2Sjpk plen, nlen - plen, " %s", 162845916cd2Sjpk lname); 162945916cd2Sjpk } 163045916cd2Sjpk plen = plen + slen + 1; 163145916cd2Sjpk } 163245916cd2Sjpk free(oldlist); 163345916cd2Sjpk break; 163445916cd2Sjpk } 163545916cd2Sjpk prev = current; 163645916cd2Sjpk } 163745916cd2Sjpk 163845916cd2Sjpk remove_dev: 163945916cd2Sjpk if (remove_dev == 1) { 164045916cd2Sjpk (void) strlcpy(devname, current->devinfo.devname, size); 164145916cd2Sjpk free(current->devinfo.devname); 164245916cd2Sjpk free(current->devinfo.devlist); 164345916cd2Sjpk current->devinfo.devname = current->devinfo.devlist = NULL; 164445916cd2Sjpk prev->next = current->next; 164545916cd2Sjpk free(current); 164645916cd2Sjpk current = NULL; 164745916cd2Sjpk } 164845916cd2Sjpk if ((remove_dev == 1) && (prev->devinfo.devname == NULL)) { 164945916cd2Sjpk if (prev->next) { 165045916cd2Sjpk /* 165145916cd2Sjpk * what we removed above was the first entry 165245916cd2Sjpk * in the list. make the next entry to be the 165345916cd2Sjpk * first. 165445916cd2Sjpk */ 165545916cd2Sjpk current = prev->next; 165645916cd2Sjpk } else { 165745916cd2Sjpk /* 165845916cd2Sjpk * the matching entry was the only entry in the list 165945916cd2Sjpk * for this type. 166045916cd2Sjpk */ 166145916cd2Sjpk current = NULL; 166245916cd2Sjpk } 166345916cd2Sjpk if (flag & DA_AUDIO) 166445916cd2Sjpk dlist->audio = current; 166545916cd2Sjpk else if (flag & DA_CD) 166645916cd2Sjpk dlist->cd = current; 166745916cd2Sjpk else if (flag & DA_FLOPPY) 166845916cd2Sjpk dlist->floppy = current; 166945916cd2Sjpk else if (flag & DA_TAPE) 167045916cd2Sjpk dlist->tape = current; 167145916cd2Sjpk else if (flag & DA_RMDISK) 167245916cd2Sjpk dlist->rmdisk = current; 167345916cd2Sjpk } 167445916cd2Sjpk 167545916cd2Sjpk return (flag); 167645916cd2Sjpk } 167745916cd2Sjpk 167845916cd2Sjpk /* 167945916cd2Sjpk * da_is_on - 168045916cd2Sjpk * checks if device allocation feature is turned on. 168145916cd2Sjpk * returns 1 if on, 0 if off, -1 if status string not 168245916cd2Sjpk * found in device_allocate. 168345916cd2Sjpk */ 168445916cd2Sjpk int 168545916cd2Sjpk da_is_on() 168645916cd2Sjpk { 168745916cd2Sjpk return (getdaon()); 168845916cd2Sjpk } 168945916cd2Sjpk 169045916cd2Sjpk /* 169145916cd2Sjpk * da_print_device - 169245916cd2Sjpk * debug routine to print device entries. 169345916cd2Sjpk */ 169445916cd2Sjpk void 169545916cd2Sjpk da_print_device(int flag, devlist_t *devlist) 169645916cd2Sjpk { 169745916cd2Sjpk deventry_t *entry, *dentry; 169845916cd2Sjpk devinfo_t *devinfo; 169945916cd2Sjpk 170045916cd2Sjpk if (flag & DA_AUDIO) 170145916cd2Sjpk dentry = devlist->audio; 170245916cd2Sjpk else if (flag & DA_CD) 170345916cd2Sjpk dentry = devlist->cd; 170445916cd2Sjpk else if (flag & DA_FLOPPY) 170545916cd2Sjpk dentry = devlist->floppy; 170645916cd2Sjpk else if (flag & DA_TAPE) 170745916cd2Sjpk dentry = devlist->tape; 170845916cd2Sjpk else if (flag & DA_RMDISK) 170945916cd2Sjpk dentry = devlist->rmdisk; 171045916cd2Sjpk else 171145916cd2Sjpk return; 171245916cd2Sjpk 171345916cd2Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 171445916cd2Sjpk devinfo = &(entry->devinfo); 171545916cd2Sjpk (void) fprintf(stdout, "name: %s\n", devinfo->devname); 171645916cd2Sjpk (void) fprintf(stdout, "type: %s\n", devinfo->devtype); 171745916cd2Sjpk (void) fprintf(stdout, "auth: %s\n", devinfo->devauths); 171845916cd2Sjpk (void) fprintf(stdout, "exec: %s\n", devinfo->devexec); 171945916cd2Sjpk (void) fprintf(stdout, "list: %s\n\n", devinfo->devlist); 172045916cd2Sjpk } 172145916cd2Sjpk } 1722