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*4514Saj * 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 #include <stdlib.h> 301676Sjpk #include <ctype.h> 311676Sjpk #include <unistd.h> 321676Sjpk #include <limits.h> 331676Sjpk #include <fcntl.h> 341676Sjpk #include <sys/types.h> 351676Sjpk #include <sys/stat.h> 361676Sjpk #include <utime.h> 371676Sjpk #include <synch.h> 381676Sjpk #include <strings.h> 391676Sjpk #include <string.h> 401676Sjpk #include <libintl.h> 411676Sjpk #include <errno.h> 421676Sjpk #include <auth_list.h> 431676Sjpk #include <bsm/devices.h> 441676Sjpk #include <bsm/devalloc.h> 451676Sjpk 461676Sjpk #define DA_DEFS "/etc/security/tsol/devalloc_defaults" 471676Sjpk 481676Sjpk extern int _readbufline(char *, int, char *, int, int *); 491676Sjpk extern char *strtok_r(char *, const char *, char **); 501676Sjpk extern char *_strtok_escape(char *, char *, char **); 511676Sjpk extern int getdaon(void); 521676Sjpk extern int da_matchname(devalloc_t *, char *); 531676Sjpk extern int da_match(devalloc_t *, da_args *); 541676Sjpk extern int dmap_matchname(devmap_t *, char *); 551676Sjpk extern int dm_match(devmap_t *, da_args *); 561676Sjpk 571676Sjpk /* 581676Sjpk * The following structure is for recording old entries to be retained. 591676Sjpk * We read the entries from the database into a linked list in memory, 601676Sjpk * then turn around and write them out again. 611676Sjpk */ 621676Sjpk typedef struct strentry { 631676Sjpk struct strentry *se_next; 641676Sjpk char se_str[4096 + 1]; 651676Sjpk } strentry_t; 661676Sjpk 671676Sjpk /* 681676Sjpk * da_check_longindevperm - 691676Sjpk * reads /etc/logindevperm and checks if specified device is in the file. 701676Sjpk * returns 1 if specified device found in /etc/logindevperm, else returns 0 711676Sjpk */ 721676Sjpk int 731676Sjpk da_check_logindevperm(char *devname) 741676Sjpk { 751676Sjpk int ret = 0; 761676Sjpk int fd = -1; 771676Sjpk int nlen, plen, slen, lineno, fsize; 781676Sjpk char line[MAX_CANON]; 791676Sjpk char *field_delims = " \t\n"; 801676Sjpk char *fbuf = NULL; 811676Sjpk char *ptr, *device; 821676Sjpk char *lasts = NULL; 831676Sjpk FILE *fp; 841676Sjpk struct stat f_stat; 851676Sjpk 861676Sjpk /* 871676Sjpk * check if /etc/logindevperm exists and get its size 881676Sjpk */ 891676Sjpk if ((fd = open(LOGINDEVPERM, O_RDONLY)) == -1) 901676Sjpk return (0); 911676Sjpk if (fstat(fd, &f_stat) != 0) { 921676Sjpk (void) close(fd); 931676Sjpk return (0); 941676Sjpk } 951676Sjpk fsize = f_stat.st_size; 961676Sjpk if ((fbuf = (char *)malloc(fsize)) == NULL) { 971676Sjpk (void) close(fd); 981676Sjpk return (0); 991676Sjpk } 1001914Scasper if ((fp = fdopen(fd, "rF")) == NULL) { 1011676Sjpk free(fbuf); 1021676Sjpk (void) close(fd); 1031676Sjpk return (0); 1041676Sjpk } 1051676Sjpk 1061676Sjpk /* 1071676Sjpk * read and parse /etc/logindevperm 1081676Sjpk */ 1091676Sjpk plen = nlen = lineno = 0; 1101676Sjpk while (fgets(line, MAX_CANON, fp) != NULL) { 1111676Sjpk lineno++; 1121676Sjpk if ((ptr = strchr(line, '#')) != NULL) 1131676Sjpk *ptr = '\0'; /* handle comments */ 1141676Sjpk if (strtok_r(line, field_delims, &lasts) == NULL) 1151676Sjpk continue; /* ignore blank lines */ 1161676Sjpk if (strtok_r(NULL, field_delims, &lasts) == NULL) 1171676Sjpk /* invalid entry */ 1181676Sjpk continue; 1191676Sjpk if ((ptr = strtok_r(NULL, field_delims, &lasts)) == NULL) 1201676Sjpk /* empty device list */ 1211676Sjpk continue; 1221676Sjpk nlen = strlen(ptr) + 1; /* +1 terminator */ 1231676Sjpk nlen += (plen + 1); 1241676Sjpk if (plen == 0) 1251676Sjpk slen = snprintf(fbuf, nlen, "%s", ptr); 1261676Sjpk else 1271676Sjpk slen = snprintf(fbuf + plen, nlen - plen, ":%s", ptr); 1281676Sjpk if (slen >= fsize) { 1291676Sjpk fbuf[0] = '\0'; 1301676Sjpk (void) fclose(fp); 1311676Sjpk return (slen); 1321676Sjpk } 1331676Sjpk plen += slen; 1341676Sjpk } 1351676Sjpk (void) fclose(fp); 1361676Sjpk 1371676Sjpk /* 1381676Sjpk * check if devname exists in /etc/logindevperm 1391676Sjpk */ 1401676Sjpk device = strtok_r(fbuf, ":", &lasts); 1411676Sjpk while (device != NULL) { 1421676Sjpk /* 1431676Sjpk * device and devname may be one of these types - 1441676Sjpk * /dev/xx 1451676Sjpk * /dev/xx* 1461676Sjpk * /dev/dir/xx 1471676Sjpk * /dev/dir/xx* 1481676Sjpk * /dev/dir/"*" 1491676Sjpk */ 1501676Sjpk if (strcmp(device, devname) == 0) { 1511676Sjpk /* /dev/xx, /dev/dir/xx */ 1521676Sjpk free(fbuf); 1531676Sjpk return (1); 1541676Sjpk } 1551676Sjpk if ((ptr = strrchr(device, KV_WILDCHAR)) != NULL) { 1561676Sjpk /* all wildcard types */ 1571676Sjpk *ptr = '\0'; 1581676Sjpk if (strncmp(device, devname, strlen(device)) == 0) { 1591676Sjpk free(fbuf); 1601676Sjpk return (1); 1611676Sjpk } 1621676Sjpk } 1631676Sjpk device = strtok_r(NULL, ":", &lasts); 1641676Sjpk } 1651676Sjpk 1661676Sjpk return (ret); 1671676Sjpk } 1681676Sjpk 1691676Sjpk /* 1701676Sjpk * _da_read_file - 1711676Sjpk * establishes readers/writer lock on fname; reads in the file if its 1721676Sjpk * contents changed since the last time we read it. 1731676Sjpk * returns size of buffer read, or -1 on failure. 1741676Sjpk */ 1751676Sjpk int 1761676Sjpk _da_read_file(char *fname, char **fbuf, time_t *ftime, rwlock_t *flock, 1771676Sjpk int flag) 1781676Sjpk { 1791676Sjpk int fd = -1; 1801676Sjpk int fsize = 0; 1811676Sjpk time_t newtime; 1821676Sjpk struct stat f_stat; 1831676Sjpk 1841676Sjpk if (flag & DA_FORCE) 1851676Sjpk *ftime = 0; 1861676Sjpk 1871676Sjpk /* check the size and the time stamp on the file */ 1881676Sjpk if (rw_rdlock(flock) != 0) 1891676Sjpk return (-1); 1901676Sjpk if (stat(fname, &f_stat) != 0) { 1911676Sjpk (void) rw_unlock(flock); 1921676Sjpk return (-1); 1931676Sjpk } 1941676Sjpk fsize = f_stat.st_size; 1951676Sjpk newtime = f_stat.st_mtime; 1961676Sjpk (void) rw_unlock(flock); 1971676Sjpk 1981676Sjpk while (newtime > *ftime) { 1991676Sjpk /* 2001676Sjpk * file has been modified since we last read it; or this 2011676Sjpk * is a forced read. 2021676Sjpk * read file into the buffer with rw lock. 2031676Sjpk */ 2041676Sjpk if (rw_wrlock(flock) != 0) 2051676Sjpk return (-1); 2061914Scasper if ((fd = open(fname, O_RDONLY)) == -1) { 2071676Sjpk (void) rw_unlock(flock); 2081676Sjpk return (-1); 2091676Sjpk } 2101676Sjpk if (*fbuf != NULL) { 2111676Sjpk free(*fbuf); 2121676Sjpk *fbuf = NULL; 2131676Sjpk } 2141676Sjpk if ((*fbuf = malloc(fsize)) == NULL) { 2151676Sjpk (void) rw_unlock(flock); 2161676Sjpk (void) close(fd); 2171676Sjpk return (-1); 2181676Sjpk } 2191676Sjpk if (read(fd, *fbuf, fsize) < fsize) { 2201676Sjpk free(*fbuf); 2211676Sjpk (void) rw_unlock(flock); 2221676Sjpk (void) close(fd); 2231676Sjpk return (-1); 2241676Sjpk } 2251676Sjpk (void) rw_unlock(flock); 2261676Sjpk /* 2271676Sjpk * verify that the file did not change just after we read it. 2281676Sjpk */ 2291676Sjpk if (rw_rdlock(flock) != 0) { 2301676Sjpk free(*fbuf); 2311676Sjpk (void) close(fd); 2321676Sjpk return (-1); 2331676Sjpk } 2341676Sjpk if (stat(fname, &f_stat) != 0) { 2351676Sjpk free(*fbuf); 2361676Sjpk (void) rw_unlock(flock); 2371676Sjpk (void) close(fd); 2381676Sjpk return (-1); 2391676Sjpk } 2401676Sjpk fsize = f_stat.st_size; 2411676Sjpk newtime = f_stat.st_mtime; 2421676Sjpk (void) rw_unlock(flock); 2431676Sjpk (void) close(fd); 2441676Sjpk *ftime = newtime; 2451676Sjpk } 2461676Sjpk 2471676Sjpk return (fsize); 2481676Sjpk } 2491676Sjpk 2501676Sjpk /* 2511676Sjpk * _update_zonename - 2521676Sjpk * add/remove current zone's name to the given devalloc_t. 2531676Sjpk */ 2541676Sjpk void 2551676Sjpk _update_zonename(da_args *dargs, devalloc_t *dap) 2561676Sjpk { 2571676Sjpk int i, j; 2581676Sjpk int oldsize, newsize; 2591676Sjpk int has_zonename = 0; 2601676Sjpk char *zonename; 2611676Sjpk kva_t *newkva, *oldkva; 2621676Sjpk kv_t *newdata, *olddata; 2631676Sjpk devinfo_t *devinfo; 2641676Sjpk 2651676Sjpk devinfo = dargs->devinfo; 2661676Sjpk oldkva = dap->da_devopts; 2671676Sjpk if (oldkva == NULL) { 2681676Sjpk if (dargs->optflag & DA_REMOVE_ZONE) 2691676Sjpk return; 2701676Sjpk if (dargs->optflag & DA_ADD_ZONE) { 2711676Sjpk newkva = _str2kva(devinfo->devopts, KV_ASSIGN, 2721676Sjpk KV_TOKEN_DELIMIT); 2731676Sjpk if (newkva != NULL) 2741676Sjpk dap->da_devopts = newkva; 2751676Sjpk return; 2761676Sjpk } 2771676Sjpk } 2781676Sjpk newsize = oldsize = oldkva->length; 2791676Sjpk if (kva_match(oldkva, DAOPT_ZONE)) 2801676Sjpk has_zonename = 1; 2811676Sjpk if (dargs->optflag & DA_ADD_ZONE) { 2821676Sjpk if ((zonename = index(devinfo->devopts, '=')) == NULL) 2831676Sjpk return; 2841676Sjpk zonename++; 2851676Sjpk if (has_zonename) { 2861676Sjpk (void) _insert2kva(oldkva, DAOPT_ZONE, zonename); 2871676Sjpk return; 2881676Sjpk } 2891676Sjpk newsize += 1; 2901676Sjpk } else if (dargs->optflag & DA_REMOVE_ZONE) { 2911676Sjpk if (has_zonename) { 2921676Sjpk newsize -= 1; 2931676Sjpk if (newsize == 0) { 2941676Sjpk /* 2951676Sjpk * If zone name was the only key/value pair, 2961676Sjpk * put 'reserved' in the empty slot. 2971676Sjpk */ 2981676Sjpk _kva_free(oldkva); 2991676Sjpk dap->da_devopts = NULL; 3001676Sjpk return; 3011676Sjpk } 3021676Sjpk } else { 3031676Sjpk return; 3041676Sjpk } 3051676Sjpk } 3061676Sjpk newkva = _new_kva(newsize); 3071676Sjpk newkva->length = 0; 3081676Sjpk newdata = newkva->data; 3091676Sjpk olddata = oldkva->data; 3101676Sjpk for (i = 0, j = 0; i < oldsize; i++) { 3111676Sjpk if ((dargs->optflag & DA_REMOVE_ZONE) && 3121676Sjpk (strcmp(olddata[i].key, DAOPT_ZONE) == 0)) 3131676Sjpk continue; 3141676Sjpk newdata[j].key = strdup(olddata[i].key); 3151676Sjpk newdata[j].value = strdup(olddata[i].value); 3161676Sjpk newkva->length++; 3171676Sjpk j++; 3181676Sjpk } 3191676Sjpk if (dargs->optflag & DA_ADD_ZONE) { 3201676Sjpk newdata[j].key = strdup(DAOPT_ZONE); 3211676Sjpk newdata[j].value = strdup(zonename); 3221676Sjpk newkva->length++; 3231676Sjpk } 3241676Sjpk _kva_free(oldkva); 3251676Sjpk dap->da_devopts = newkva; 3261676Sjpk } 3271676Sjpk 3281676Sjpk /* 3291676Sjpk * _dmap2str - 3301676Sjpk * converts a device_map entry into a printable string 3311676Sjpk * returns 0 on success, -1 on error. 3321676Sjpk */ 3331676Sjpk /*ARGSUSED*/ 3341676Sjpk static int 3351676Sjpk _dmap2str(da_args *dargs, devmap_t *dmp, char *buf, int size, const char *sep) 3361676Sjpk { 3371676Sjpk int length; 3381676Sjpk 3391676Sjpk length = snprintf(buf, size, "%s%s", dmp->dmap_devname, sep); 3401676Sjpk if (length >= size) 3411676Sjpk return (-1); 3421676Sjpk length += snprintf(buf + length, size - length, "%s%s", 3431676Sjpk dmp->dmap_devtype, sep); 3441676Sjpk if (length >= size) 3451676Sjpk return (-1); 3461676Sjpk length += snprintf(buf + length, size - length, "%s\n", 3471676Sjpk dmp->dmap_devlist); 3481676Sjpk if (length >= size) 3491676Sjpk return (-1); 3501676Sjpk return (0); 3511676Sjpk } 3521676Sjpk 3531676Sjpk /* 3541676Sjpk * _dmap2strentry - 3551676Sjpk * calls dmap2str to break given devmap_t into printable entry. 3561676Sjpk * returns pointer to decoded entry, NULL on error. 3571676Sjpk */ 3581676Sjpk static strentry_t * 3591676Sjpk _dmap2strentry(da_args *dargs, devmap_t *devmapp) 3601676Sjpk { 3611676Sjpk strentry_t *sep; 3621676Sjpk 3631676Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 3641676Sjpk return (NULL); 3651676Sjpk if (_dmap2str(dargs, devmapp, sep->se_str, sizeof (sep->se_str), 3661676Sjpk KV_TOKEN_DELIMIT"\\\n\t") != 0) { 3671676Sjpk free(sep); 3681676Sjpk return (NULL); 3691676Sjpk } 3701676Sjpk return (sep); 3711676Sjpk } 3721676Sjpk 3731676Sjpk /* 3741676Sjpk * fix_optstr - 3751676Sjpk * removes trailing ':' from buf. 3761676Sjpk */ 3771676Sjpk void 3781676Sjpk fix_optstr(char *buf) 3791676Sjpk { 3801676Sjpk char *p = NULL; 3811676Sjpk 3821676Sjpk if (p = rindex(buf, ':')) 3831676Sjpk *p = ';'; 3841676Sjpk } 3851676Sjpk 3861676Sjpk /* 3871676Sjpk * _da2str - 3881676Sjpk * converts a device_allocate entry into a printable string 3891676Sjpk * returns 0 on success, -1 on error. 3901676Sjpk */ 3911676Sjpk static int 3921676Sjpk _da2str(da_args *dargs, devalloc_t *dap, char *buf, int size, const char *sep, 3931676Sjpk const char *osep) 3941676Sjpk { 3951676Sjpk int length; 3961676Sjpk int matching_entry = 0; 3971676Sjpk char **dnames; 3981676Sjpk 3991676Sjpk if (dargs->optflag & DA_UPDATE && 4001676Sjpk (dargs->optflag & DA_ADD_ZONE || 4011676Sjpk dargs->optflag & DA_REMOVE_ZONE) && 4021676Sjpk dargs->devnames) { 4031676Sjpk for (dnames = dargs->devnames; *dnames != NULL; dnames++) { 4041676Sjpk if (da_matchname(dap, *dnames)) { 4051676Sjpk matching_entry = 1; 4061676Sjpk break; 4071676Sjpk } 4081676Sjpk } 4091676Sjpk } 4101676Sjpk length = snprintf(buf, size, "%s%s", dap->da_devname, sep); 4111676Sjpk if (length >= size) 4121676Sjpk return (-1); 4131676Sjpk length += snprintf(buf + length, size - length, "%s%s", 4141676Sjpk dap->da_devtype, sep); 4151676Sjpk if (length >= size) 4161676Sjpk return (-1); 4171676Sjpk if (matching_entry) 4181676Sjpk _update_zonename(dargs, dap); 4191676Sjpk if ((dap->da_devopts == NULL) || ((dap->da_devopts->length == 1) && 4201676Sjpk (strcmp(dap->da_devopts->data->key, DA_RESERVED) == 0))) { 4211676Sjpk length += snprintf(buf + length, size - length, "%s%s", 4221676Sjpk DA_RESERVED, sep); 4231676Sjpk } else { 4241676Sjpk if (_kva2str(dap->da_devopts, buf + length, size - length, 4251676Sjpk KV_ASSIGN, (char *)osep) != 0) 4261676Sjpk return (-1); 4271676Sjpk length = strlen(buf); 4281676Sjpk } 4291676Sjpk if (dap->da_devopts) 4301676Sjpk fix_optstr(buf); 4311676Sjpk if (length >= size) 4321676Sjpk return (-1); 4331676Sjpk length += snprintf(buf + length, size - length, "%s%s", 4341676Sjpk DA_RESERVED, sep); 4351676Sjpk if (length >= size) 4361676Sjpk return (-1); 4371676Sjpk length += snprintf(buf + length, size - length, "%s%s", 4381676Sjpk dap->da_devauth ? dap->da_devauth : DA_ANYUSER, sep); 4391676Sjpk if (length >= size) 4401676Sjpk return (-1); 4411676Sjpk length += snprintf(buf + length, size - length, "%s\n", 4421676Sjpk dap->da_devexec ? dap->da_devexec : ""); 4431676Sjpk if (length >= size) 4441676Sjpk return (-1); 4451676Sjpk 4461676Sjpk return (0); 4471676Sjpk } 4481676Sjpk 4491676Sjpk /* 4501676Sjpk * _da2strentry - 4511676Sjpk * calls da2str to break given devalloc_t into printable entry. 4521676Sjpk * returns pointer to decoded entry, NULL on error. 4531676Sjpk */ 4541676Sjpk static strentry_t * 4551676Sjpk _da2strentry(da_args *dargs, devalloc_t *dap) 4561676Sjpk { 4571676Sjpk strentry_t *sep; 4581676Sjpk 4591676Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 4601676Sjpk return (NULL); 4611676Sjpk if (_da2str(dargs, dap, sep->se_str, sizeof (sep->se_str), 4621676Sjpk KV_DELIMITER "\\\n\t", KV_TOKEN_DELIMIT "\\\n\t") != 0) { 4631676Sjpk free(sep); 4641676Sjpk return (NULL); 4651676Sjpk } 4661676Sjpk return (sep); 4671676Sjpk } 4681676Sjpk 4691676Sjpk /* 4701676Sjpk * _def2str 4711676Sjpk * converts da_defs_t into a printable string. 4721676Sjpk * returns 0 on success, -1 on error. 4731676Sjpk */ 4741676Sjpk static int 4751676Sjpk _def2str(da_defs_t *da_defs, char *buf, int size, const char *sep) 4761676Sjpk { 4771676Sjpk int length; 4781676Sjpk 4791676Sjpk length = snprintf(buf, size, "%s%s", da_defs->devtype, sep); 4801676Sjpk if (length >= size) 4811676Sjpk return (-1); 4821676Sjpk if (da_defs->devopts) { 4831676Sjpk if (_kva2str(da_defs->devopts, buf + length, size - length, 4841676Sjpk KV_ASSIGN, KV_DELIMITER) != 0) 4851676Sjpk return (-1); 4861676Sjpk length = strlen(buf); 4871676Sjpk } 4881676Sjpk if (length >= size) 4891676Sjpk return (-1); 4901676Sjpk 4911676Sjpk return (0); 4921676Sjpk } 4931676Sjpk 4941676Sjpk /* 4951676Sjpk * _def2strentry 4961676Sjpk * calls _def2str to break given da_defs_t into printable entry. 4971676Sjpk * returns pointer decoded entry, NULL on error. 4981676Sjpk */ 4991676Sjpk static strentry_t * 5001676Sjpk _def2strentry(da_defs_t *da_defs) 5011676Sjpk { 5021676Sjpk strentry_t *sep; 5031676Sjpk 5041676Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 5051676Sjpk return (NULL); 5061676Sjpk if (_def2str(da_defs, sep->se_str, sizeof (sep->se_str), 5071676Sjpk KV_TOKEN_DELIMIT) != 0) { 5081676Sjpk free(sep); 5091676Sjpk return (NULL); 5101676Sjpk } 5111676Sjpk 5121676Sjpk return (sep); 5131676Sjpk } 5141676Sjpk 5151676Sjpk /* 5161676Sjpk * _build_defattrs 5171676Sjpk * cycles through all defattr entries, stores them in memory. removes 5181676Sjpk * entries with the given search_key (device type). 5191676Sjpk * returns 0 if given entry not found, 1 if given entry removed, 2 on 5201676Sjpk * error. 5211676Sjpk */ 5221676Sjpk static int 5231676Sjpk _build_defattrs(da_args *dargs, strentry_t **head_defent) 5241676Sjpk { 5251676Sjpk int rc = 0; 5261676Sjpk da_defs_t *da_defs; 5271676Sjpk strentry_t *tail_str, *tmp_str; 5281676Sjpk 5291676Sjpk setdadefent(); 5301676Sjpk while ((da_defs = getdadefent()) != NULL) { 5311676Sjpk rc = !(strcmp(da_defs->devtype, dargs->devinfo->devtype)); 5321676Sjpk if (rc && dargs->optflag & DA_ADD && 5331676Sjpk !(dargs->optflag & DA_FORCE)) { 5341676Sjpk /* 5351676Sjpk * During DA_ADD, we keep an existing entry unless 5361676Sjpk * we have DA_FORCE set to override that entry. 5371676Sjpk */ 5381676Sjpk dargs->optflag |= DA_NO_OVERRIDE; 5391676Sjpk rc = 0; 5401676Sjpk } 5411676Sjpk if (rc == 0) { 5421676Sjpk tmp_str = _def2strentry(da_defs); 5431676Sjpk if (tmp_str == NULL) { 5441676Sjpk freedadefent(da_defs); 5451676Sjpk enddadefent(); 5461676Sjpk return (2); 5471676Sjpk } 5481676Sjpk /* retaining defattr entry: tmp_str->se_str */ 5491676Sjpk tmp_str->se_next = NULL; 5501676Sjpk if (*head_defent == NULL) { 5511676Sjpk *head_defent = tail_str = tmp_str; 5521676Sjpk } else { 5531676Sjpk tail_str->se_next = tmp_str; 5541676Sjpk tail_str = tmp_str; 5551676Sjpk } 5561676Sjpk } 5571676Sjpk freedadefent(da_defs); 5581676Sjpk } 5591676Sjpk enddadefent(); 5601676Sjpk 5611676Sjpk return (rc); 5621676Sjpk } 5631676Sjpk 5641676Sjpk /* 5651676Sjpk * _build_lists - 5661676Sjpk * cycles through all the entries, stores them in memory. removes entries 5671676Sjpk * with the given search_key (device name or type). 5681676Sjpk * returns 0 if given entry not found, 1 if given entry removed, 2 on 5691676Sjpk * error. 5701676Sjpk */ 5711676Sjpk static int 5721676Sjpk _build_lists(da_args *dargs, strentry_t **head_devallocp, 5731676Sjpk strentry_t **head_devmapp) 5741676Sjpk { 5751676Sjpk int rc = 0; 5761676Sjpk devalloc_t *devallocp; 5771676Sjpk devmap_t *devmapp; 5781676Sjpk strentry_t *tail_str; 5791676Sjpk strentry_t *tmp_str; 5801676Sjpk 5811676Sjpk if (dargs->optflag & DA_MAPS_ONLY) 5821676Sjpk goto dmap_only; 5831676Sjpk 5841676Sjpk /* build device_allocate */ 5851676Sjpk setdaent(); 5861676Sjpk while ((devallocp = getdaent()) != NULL) { 5871676Sjpk rc = da_match(devallocp, dargs); 5881676Sjpk if (rc && dargs->optflag & DA_ADD && 5891676Sjpk !(dargs->optflag & DA_FORCE)) { 5901676Sjpk /* 5911676Sjpk * During DA_ADD, we keep an existing entry unless 5921676Sjpk * we have DA_FORCE set to override that entry. 5931676Sjpk */ 5941676Sjpk dargs->optflag |= DA_NO_OVERRIDE; 5951676Sjpk rc = 0; 5961676Sjpk } 5971676Sjpk if (rc == 0) { 5981676Sjpk tmp_str = _da2strentry(dargs, devallocp); 5991676Sjpk if (tmp_str == NULL) { 6001676Sjpk freedaent(devallocp); 6011676Sjpk enddaent(); 6021676Sjpk return (2); 6031676Sjpk } 6041676Sjpk /* retaining devalloc entry: tmp_str->se_str */ 6051676Sjpk tmp_str->se_next = NULL; 6061676Sjpk if (*head_devallocp == NULL) { 6071676Sjpk *head_devallocp = tail_str = tmp_str; 6081676Sjpk } else { 6091676Sjpk tail_str->se_next = tmp_str; 6101676Sjpk tail_str = tmp_str; 6111676Sjpk } 6121676Sjpk } 6131676Sjpk freedaent(devallocp); 6141676Sjpk } 6151676Sjpk enddaent(); 6161676Sjpk 6171676Sjpk dmap_only: 6181676Sjpk if (dargs->optflag & DA_ALLOC_ONLY) 6191676Sjpk return (rc); 6201676Sjpk 6211676Sjpk /* build device_maps */ 6221676Sjpk rc = 0; 6231676Sjpk setdmapent(); 6241676Sjpk while ((devmapp = getdmapent()) != NULL) { 6251676Sjpk rc = dm_match(devmapp, dargs); 6261676Sjpk if (rc && dargs->optflag & DA_ADD && 6271676Sjpk !(dargs->optflag & DA_FORCE)) { 6281676Sjpk /* 6291676Sjpk * During DA_ADD, we keep an existing entry unless 6301676Sjpk * we have DA_FORCE set to override that entry. 6311676Sjpk */ 6321676Sjpk dargs->optflag |= DA_NO_OVERRIDE; 6331676Sjpk rc = 0; 6341676Sjpk } 6351676Sjpk if (rc == 0) { 6361676Sjpk tmp_str = _dmap2strentry(dargs, devmapp); 6371676Sjpk if (tmp_str == NULL) { 6381676Sjpk freedmapent(devmapp); 6391676Sjpk enddmapent(); 6401676Sjpk return (2); 6411676Sjpk } 6421676Sjpk /* retaining devmap entry: tmp_str->se_str */ 6431676Sjpk tmp_str->se_next = NULL; 6441676Sjpk if (*head_devmapp == NULL) { 6451676Sjpk *head_devmapp = tail_str = tmp_str; 6461676Sjpk } else { 6471676Sjpk tail_str->se_next = tmp_str; 6481676Sjpk tail_str = tmp_str; 6491676Sjpk } 6501676Sjpk } 6511676Sjpk freedmapent(devmapp); 6521676Sjpk } 6531676Sjpk enddmapent(); 6541676Sjpk 6551676Sjpk return (rc); 6561676Sjpk } 6571676Sjpk 6581676Sjpk /* 6591676Sjpk * _write_defattrs 6601676Sjpk * writes current entries to devalloc_defaults. 6611676Sjpk */ 6621676Sjpk static void 6631676Sjpk _write_defattrs(FILE *fp, strentry_t *head_defent) 6641676Sjpk { 6651676Sjpk strentry_t *tmp_str; 6661676Sjpk 6671676Sjpk for (tmp_str = head_defent; tmp_str != NULL; 6681676Sjpk tmp_str = tmp_str->se_next) { 6691676Sjpk (void) fputs(tmp_str->se_str, fp); 6701676Sjpk (void) fputs("\n", fp); 6711676Sjpk } 6721676Sjpk 6731676Sjpk } 6741676Sjpk 6751676Sjpk /* 6761676Sjpk * _write_device_allocate - 6771676Sjpk * writes current entries in the list to device_allocate. 6781676Sjpk */ 6791676Sjpk static void 6801676Sjpk _write_device_allocate(char *odevalloc, FILE *dafp, strentry_t *head_devallocp) 6811676Sjpk { 6821676Sjpk int is_on = -1; 6831676Sjpk strentry_t *tmp_str; 6841676Sjpk struct stat dastat; 6851676Sjpk 6861676Sjpk (void) fseek(dafp, (off_t)0, SEEK_SET); 6871676Sjpk 6881676Sjpk /* 6891676Sjpk * if the devalloc on/off string existed before, 6901676Sjpk * put it back before anything else. 6911676Sjpk * we need to check for the string only if the file 6921676Sjpk * exists. 6931676Sjpk */ 6941676Sjpk if (stat(odevalloc, &dastat) == 0) { 6951676Sjpk is_on = da_is_on(); 6961676Sjpk if (is_on == 0) 6971676Sjpk (void) fputs(DA_OFF_STR, dafp); 6981676Sjpk else if (is_on == 1) 6991676Sjpk (void) fputs(DA_ON_STR, dafp); 7001676Sjpk } 7011676Sjpk tmp_str = head_devallocp; 7021676Sjpk while (tmp_str) { 7031676Sjpk (void) fputs(tmp_str->se_str, dafp); 7041676Sjpk (void) fputs("\n", dafp); 7051676Sjpk tmp_str = tmp_str->se_next; 7061676Sjpk } 7071676Sjpk } 7081676Sjpk 7091676Sjpk /* 7101676Sjpk * _write_device_maps - 7111676Sjpk * writes current entries in the list to device_maps. 7121676Sjpk */ 7131676Sjpk static void 7141676Sjpk _write_device_maps(FILE *dmfp, strentry_t *head_devmapp) 7151676Sjpk { 7161676Sjpk strentry_t *tmp_str; 7171676Sjpk 7181676Sjpk (void) fseek(dmfp, (off_t)0, SEEK_SET); 7191676Sjpk 7201676Sjpk tmp_str = head_devmapp; 7211676Sjpk while (tmp_str) { 7221676Sjpk (void) fputs(tmp_str->se_str, dmfp); 7231676Sjpk (void) fputs("\n", dmfp); 7241676Sjpk tmp_str = tmp_str->se_next; 7251676Sjpk } 7261676Sjpk } 7271676Sjpk 7281676Sjpk /* 7291676Sjpk * _write_new_defattrs 7301676Sjpk * writes the new entry to devalloc_defaults. 7311676Sjpk * returns 0 on success, -1 on error. 7321676Sjpk */ 7331676Sjpk static int 7341676Sjpk _write_new_defattrs(FILE *fp, da_args *dargs) 7351676Sjpk { 7361676Sjpk int count; 7371676Sjpk char *tok = NULL, *tokp = NULL; 7381676Sjpk char *lasts; 7391676Sjpk devinfo_t *devinfo = dargs->devinfo; 7401676Sjpk 7411676Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 7421676Sjpk return (-1); 7431676Sjpk if (!devinfo->devopts) 7441676Sjpk return (0); 7451676Sjpk (void) fprintf(fp, "%s%s", (devinfo->devtype ? devinfo->devtype : ""), 7461676Sjpk KV_TOKEN_DELIMIT); 7471676Sjpk if ((tokp = (char *)malloc(strlen(devinfo->devopts))) != NULL) { 7481676Sjpk (void) strcpy(tokp, devinfo->devopts); 7491676Sjpk if ((tok = strtok_r(tokp, KV_DELIMITER, &lasts)) != NULL) { 7501676Sjpk (void) fprintf(fp, "%s", tok); 7511676Sjpk count = 1; 7521676Sjpk } 7531676Sjpk while ((tok = strtok_r(NULL, KV_DELIMITER, &lasts)) != NULL) { 7541676Sjpk if (count) 7551676Sjpk (void) fprintf(fp, "%s", KV_DELIMITER); 7561676Sjpk (void) fprintf(fp, "%s", tok); 7571676Sjpk count++; 7581676Sjpk } 7591676Sjpk } else { 7601676Sjpk (void) fprintf(fp, "%s", devinfo->devopts); 7611676Sjpk } 7621676Sjpk 7631676Sjpk return (0); 7641676Sjpk } 7651676Sjpk 7661676Sjpk /* 7671676Sjpk * _write_new_entry - 7681676Sjpk * writes the new devalloc_t to device_allocate or the new devmap_t to 7691676Sjpk * device_maps. 7701676Sjpk * returns 0 on success, -1 on error. 7711676Sjpk */ 7721676Sjpk static int 7731676Sjpk _write_new_entry(FILE *fp, da_args *dargs, int flag) 7741676Sjpk { 7751676Sjpk int count; 7761676Sjpk char *tok = NULL, *tokp = NULL; 7771676Sjpk char *lasts; 7781676Sjpk devinfo_t *devinfo = dargs->devinfo; 7791676Sjpk 7801676Sjpk if (flag & DA_MAPS_ONLY) 7811676Sjpk goto dmap_only; 7821676Sjpk 7831676Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 7841676Sjpk return (-1); 7851676Sjpk 7861676Sjpk (void) fprintf(fp, "%s%s\\\n\t", 7871676Sjpk (devinfo->devname ? devinfo->devname : ""), KV_DELIMITER); 7881676Sjpk (void) fprintf(fp, "%s%s\\\n\t", 7891676Sjpk (devinfo->devtype ? devinfo->devtype : ""), KV_DELIMITER); 7901676Sjpk if (devinfo->devopts == NULL) { 7911676Sjpk (void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED, 7921676Sjpk KV_DELIMITER); 7931676Sjpk } else { 7941676Sjpk if ((tokp = (char *)malloc(strlen(devinfo->devopts))) != NULL) { 7951676Sjpk (void) strcpy(tokp, devinfo->devopts); 7961676Sjpk if ((tok = strtok_r(tokp, KV_TOKEN_DELIMIT, &lasts)) != 7971676Sjpk NULL) { 7981676Sjpk (void) fprintf(fp, "%s", tok); 7991676Sjpk count = 1; 8001676Sjpk } 8011676Sjpk while ((tok = strtok_r(NULL, KV_TOKEN_DELIMIT, 8021676Sjpk &lasts)) != NULL) { 8031676Sjpk if (count) 8041676Sjpk (void) fprintf(fp, "%s", 8051676Sjpk KV_TOKEN_DELIMIT "\\\n\t"); 8061676Sjpk (void) fprintf(fp, "%s", tok); 8071676Sjpk count++; 8081676Sjpk } 8091676Sjpk if (count) 8101676Sjpk (void) fprintf(fp, "%s", 8111676Sjpk KV_DELIMITER "\\\n\t"); 8121676Sjpk } else { 8131676Sjpk (void) fprintf(fp, "%s%s", devinfo->devopts, 8141676Sjpk KV_DELIMITER "\\\n\t"); 8151676Sjpk } 8161676Sjpk } 8171676Sjpk (void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED, KV_DELIMITER); 8181676Sjpk (void) fprintf(fp, "%s%s\\\n\t", 8191676Sjpk (devinfo->devauths ? devinfo->devauths : DA_ANYUSER), 8201676Sjpk KV_DELIMITER); 8211676Sjpk (void) fprintf(fp, "%s\n", 8221676Sjpk (devinfo->devexec ? devinfo->devexec : KV_DELIMITER)); 8231676Sjpk 8241676Sjpk dmap_only: 8251676Sjpk if (flag & DA_ALLOC_ONLY) 8261676Sjpk return (0); 8271676Sjpk 8281676Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 8291676Sjpk return (-1); 8301676Sjpk 8311676Sjpk (void) fprintf(fp, "%s%s\\\n", 8321676Sjpk (devinfo->devname ? devinfo->devname : ""), KV_TOKEN_DELIMIT); 8331676Sjpk (void) fprintf(fp, "\t%s%s\\\n", 8341676Sjpk (devinfo->devtype ? devinfo->devtype : ""), KV_TOKEN_DELIMIT); 8351676Sjpk (void) fprintf(fp, "\t%s\n", 8361676Sjpk (devinfo->devlist ? devinfo->devlist : KV_TOKEN_DELIMIT)); 8371676Sjpk 8381676Sjpk return (0); 8391676Sjpk } 8401676Sjpk 8411676Sjpk /* 8421676Sjpk * _da_lock_devdb - 8431676Sjpk * locks the database files; lock can be either broken explicitly by 8441676Sjpk * closing the fd of the lock file, or it expires automatically at process 8451676Sjpk * termination. 8461676Sjpk * returns fd of the lock file or -1 on error. 8471676Sjpk */ 8481676Sjpk int 8491676Sjpk _da_lock_devdb(char *rootdir) 8501676Sjpk { 8511676Sjpk int lockfd = -1; 852*4514Saj int ret; 853*4514Saj int count = 0; 854*4514Saj int retry = 10; 855*4514Saj int retry_sleep; 856*4514Saj uint_t seed; 8571676Sjpk char *lockfile; 8581676Sjpk char path[MAXPATHLEN]; 8591676Sjpk int size = sizeof (path); 8601676Sjpk 8611676Sjpk if (rootdir == NULL) { 8621676Sjpk lockfile = DA_DB_LOCK; 8631676Sjpk } else { 8641676Sjpk path[0] = '\0'; 8651676Sjpk if (snprintf(path, size, "%s%s", rootdir, DA_DB_LOCK) >= size) 8661676Sjpk return (-1); 8671676Sjpk lockfile = path; 8681676Sjpk } 8691676Sjpk 8701676Sjpk if ((lockfd = open(lockfile, O_RDWR | O_CREAT, 0600)) == -1) 8711676Sjpk /* cannot open lock file */ 8721676Sjpk return (-1); 8731676Sjpk 8741676Sjpk (void) fchown(lockfd, DA_UID, DA_GID); 8751676Sjpk 8761676Sjpk if (lseek(lockfd, (off_t)0, SEEK_SET) == -1) { 8771676Sjpk /* cannot position lock file */ 8781676Sjpk (void) close(lockfd); 8791676Sjpk return (-1); 8801676Sjpk } 881*4514Saj errno = 0; 882*4514Saj while (retry > 0) { 883*4514Saj count++; 884*4514Saj seed = (uint_t)gethrtime(); 885*4514Saj ret = lockf(lockfd, F_TLOCK, 0); 886*4514Saj if (ret == 0) { 887*4514Saj (void) utime(lockfile, NULL); 888*4514Saj return (lockfd); 889*4514Saj } 890*4514Saj if ((errno != EACCES) && (errno != EAGAIN)) { 891*4514Saj /* cannot set lock */ 892*4514Saj (void) close(lockfd); 893*4514Saj return (-1); 894*4514Saj } 895*4514Saj retry--; 896*4514Saj retry_sleep = rand_r(&seed)/((RAND_MAX + 2)/3) + count; 897*4514Saj (void) sleep(retry_sleep); 898*4514Saj errno = 0; 8991676Sjpk } 9001676Sjpk 901*4514Saj return (-1); 9021676Sjpk } 9031676Sjpk 9041676Sjpk /* 9051676Sjpk * da_open_devdb - 9061676Sjpk * opens one or both database files - device_allocate, device_maps - in 9071676Sjpk * the specified mode. 9081676Sjpk * locks the database files; lock is either broken explicitly by the 9091676Sjpk * caller by closing the lock file fd, or it expires automatically at 9101676Sjpk * process termination. 9111676Sjpk * writes the file pointer of opened file in the input args - dafp, dmfp. 9121676Sjpk * returns fd of the lock file on success, -2 if database file does not 9131676Sjpk * exist, -1 on other errors. 9141676Sjpk */ 9151676Sjpk int 9161676Sjpk da_open_devdb(char *rootdir, FILE **dafp, FILE **dmfp, int flag) 9171676Sjpk { 9181676Sjpk int oflag = 0; 9191676Sjpk int fda = -1; 9201676Sjpk int fdm = -1; 9211676Sjpk int lockfd = -1; 9221676Sjpk char *fname; 9231676Sjpk char *fmode; 9241676Sjpk char path[MAXPATHLEN]; 9251676Sjpk FILE *devfile; 9261676Sjpk 9271676Sjpk if ((dafp == NULL) && (dmfp == NULL)) 9281676Sjpk return (-1); 9291676Sjpk 9301676Sjpk if (flag & DA_RDWR) { 9311676Sjpk oflag = DA_RDWR; 9321914Scasper fmode = "r+F"; 9331676Sjpk } else if (flag & DA_RDONLY) { 9341676Sjpk oflag = DA_RDONLY; 9351914Scasper fmode = "rF"; 9361676Sjpk } 9371676Sjpk 9381676Sjpk if ((lockfd = _da_lock_devdb(rootdir)) == -1) 9391676Sjpk return (-1); 9401676Sjpk 9411676Sjpk if ((dafp == NULL) || (flag & DA_MAPS_ONLY)) 9421676Sjpk goto dmap_only; 9431676Sjpk 9441676Sjpk path[0] = '\0'; 9451676Sjpk 9461676Sjpk /* 9471676Sjpk * open the device allocation file 9481676Sjpk */ 9491676Sjpk if (rootdir == NULL) { 9501676Sjpk fname = DEVALLOC; 9511676Sjpk } else { 9521676Sjpk if (snprintf(path, sizeof (path), "%s%s", rootdir, 9531676Sjpk DEVALLOC) >= sizeof (path)) { 9541676Sjpk if (lockfd != -1) 9551676Sjpk (void) close(lockfd); 9561676Sjpk return (-1); 9571676Sjpk } 9581676Sjpk fname = path; 9591676Sjpk } 9601676Sjpk if ((fda = open(fname, oflag, DA_DBMODE)) == -1) { 9611676Sjpk if (lockfd != -1) 9621676Sjpk (void) close(lockfd); 9631676Sjpk return ((errno == ENOENT) ? -2 : -1); 9641676Sjpk } 9651676Sjpk if ((devfile = fdopen(fda, fmode)) == NULL) { 9661676Sjpk (void) close(fda); 9671676Sjpk if (lockfd != -1) 9681676Sjpk (void) close(lockfd); 9691676Sjpk return (-1); 9701676Sjpk } 9711676Sjpk *dafp = devfile; 9721676Sjpk (void) fchmod(fda, DA_DBMODE); 9731676Sjpk 9741676Sjpk if ((flag & DA_ALLOC_ONLY)) 9751676Sjpk goto out; 9761676Sjpk 9771676Sjpk dmap_only: 9781676Sjpk path[0] = '\0'; 9791676Sjpk /* 9801676Sjpk * open the device map file 9811676Sjpk */ 9821676Sjpk if (rootdir == NULL) { 9831676Sjpk fname = DEVMAP; 9841676Sjpk } else { 9851676Sjpk if (snprintf(path, sizeof (path), "%s%s", rootdir, 9861676Sjpk DEVMAP) >= sizeof (path)) { 9871676Sjpk (void) close(fda); 9881676Sjpk if (lockfd != -1) 9891676Sjpk (void) close(lockfd); 9901676Sjpk return (-1); 9911676Sjpk } 9921676Sjpk fname = path; 9931676Sjpk } 9941676Sjpk 9951676Sjpk if ((fdm = open(fname, oflag, DA_DBMODE)) == -1) { 9961676Sjpk if (lockfd != -1) 9971676Sjpk (void) close(lockfd); 9981676Sjpk return ((errno == ENOENT) ? -2 : -1); 9991676Sjpk } 10001676Sjpk 10011676Sjpk if ((devfile = fdopen(fdm, fmode)) == NULL) { 10021676Sjpk (void) close(fdm); 10031676Sjpk (void) close(fda); 10041676Sjpk if (lockfd != -1) 10051676Sjpk (void) close(lockfd); 10061676Sjpk return (-1); 10071676Sjpk } 10081676Sjpk *dmfp = devfile; 10091676Sjpk (void) fchmod(fdm, DA_DBMODE); 10101676Sjpk 10111676Sjpk out: 10121676Sjpk return (lockfd); 10131676Sjpk } 10141676Sjpk 10151676Sjpk /* 10161676Sjpk * _record_on_off - 10171676Sjpk * adds either DA_ON_STR or DA_OFF_STR to device_allocate 10181676Sjpk * returns 0 on success, -1 on error. 10191676Sjpk */ 10201676Sjpk static int 10211676Sjpk _record_on_off(da_args *dargs, FILE *tafp, FILE *dafp) 10221676Sjpk { 10231676Sjpk int dafd; 10241676Sjpk int nsize; 10251676Sjpk int nitems = 1; 10261676Sjpk int actionlen; 10271676Sjpk int str_found = 0; 10281676Sjpk int len = 0, nlen = 0, plen = 0; 10291676Sjpk char *ptr = NULL; 10301676Sjpk char *actionstr; 10311676Sjpk char *nbuf = NULL; 10321676Sjpk char line[MAX_CANON]; 10331676Sjpk struct stat dastat; 10341676Sjpk 10351676Sjpk if (dargs->optflag & DA_ON) 10361676Sjpk actionstr = DA_ON_STR; 10371676Sjpk else 10381676Sjpk actionstr = DA_OFF_STR; 10391676Sjpk actionlen = strlen(actionstr); 10401676Sjpk dafd = fileno(dafp); 10411676Sjpk if (fstat(dafd, &dastat) == -1) 10421676Sjpk return (-1); 10431676Sjpk 10441676Sjpk /* check the old device_allocate for on/off string */ 10451676Sjpk ptr = fgets(line, MAX_CANON, dafp); 10461676Sjpk if (ptr != NULL) { 10471676Sjpk if ((strcmp(line, DA_ON_STR) == 0) || 10481676Sjpk (strcmp(line, DA_OFF_STR) == 0)) { 10491676Sjpk str_found = 1; 10501676Sjpk nsize = dastat.st_size; 10511676Sjpk } 10521676Sjpk } 10531676Sjpk if (!ptr || !str_found) { 10541676Sjpk /* 10551676Sjpk * the file never had either the on or the off string; 10561676Sjpk * make room for it. 10571676Sjpk */ 10581676Sjpk str_found = 0; 10591676Sjpk nsize = dastat.st_size + actionlen + 1; 10601676Sjpk } 10611676Sjpk if ((nbuf = (char *)malloc(nsize)) == NULL) 10621676Sjpk return (-1); 10631676Sjpk nbuf[0] = '\0'; 10641676Sjpk /* put the on/off string */ 10651676Sjpk (void) strcpy(nbuf, actionstr); 10661676Sjpk nlen = strlen(nbuf); 10671676Sjpk plen = nlen; 10681676Sjpk if (ptr && !str_found) { 10691676Sjpk /* now put the first line that we read in fgets */ 10701676Sjpk nlen = plen + strlen(line) + 1; 10711676Sjpk len = snprintf(nbuf + plen, nlen - plen, "%s", line); 10721676Sjpk if (len >= nsize) { 10731676Sjpk free(nbuf); 10741676Sjpk return (-1); 10751676Sjpk } 10761676Sjpk plen += len; 10771676Sjpk } 10781676Sjpk 10791676Sjpk /* now get the rest of the old file */ 10801676Sjpk while (fgets(line, MAX_CANON, dafp) != NULL) { 10811676Sjpk nlen = plen + strlen(line) + 1; 10821676Sjpk len = snprintf(nbuf + plen, nlen - plen, "%s", line); 10831676Sjpk if (len >= nsize) { 10841676Sjpk free(nbuf); 10851676Sjpk return (-1); 10861676Sjpk } 10871676Sjpk plen += len; 10881676Sjpk } 10891676Sjpk len = strlen(nbuf) + 1; 10901676Sjpk if (len < nsize) 10911676Sjpk nbuf[len] = '\n'; 10921676Sjpk 10931676Sjpk /* write the on/off str + the old device_allocate to the temp file */ 10941676Sjpk if (fwrite(nbuf, nsize, nitems, tafp) < nitems) { 10951676Sjpk free(nbuf); 10961676Sjpk return (-1); 10971676Sjpk } 10981676Sjpk 10991676Sjpk free(nbuf); 11001676Sjpk 11011676Sjpk return (0); 11021676Sjpk } 11031676Sjpk 11041676Sjpk /* 11051676Sjpk * da_update_defattrs - 11061676Sjpk * writes default attributes to devalloc_defaults 11071676Sjpk * returns 0 on success, -1 on error. 11081676Sjpk */ 11091676Sjpk int 11101676Sjpk da_update_defattrs(da_args *dargs) 11111676Sjpk { 11121676Sjpk int rc = 0, lockfd = 0, tmpfd = 0; 11131676Sjpk char *defpath = DEFATTRS; 11141676Sjpk char *tmpdefpath = TMPATTRS; 11151676Sjpk FILE *tmpfp = NULL; 11161676Sjpk struct stat dstat; 11171676Sjpk strentry_t *head_defent = NULL; 11181676Sjpk 11191676Sjpk if (dargs == NULL) 11201676Sjpk return (0); 11211676Sjpk if ((lockfd = _da_lock_devdb(NULL)) == -1) 11221676Sjpk return (-1); 11231676Sjpk if ((tmpfd = open(tmpdefpath, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 11241676Sjpk (void) close(lockfd); 11251676Sjpk return (-1); 11261676Sjpk } 11271676Sjpk (void) fchown(tmpfd, DA_UID, DA_GID); 11281676Sjpk if ((tmpfp = fdopen(tmpfd, "r+")) == NULL) { 11291676Sjpk (void) close(tmpfd); 11301676Sjpk (void) unlink(tmpdefpath); 11311676Sjpk (void) close(lockfd); 11321676Sjpk return (-1); 11331676Sjpk } 11341676Sjpk /* 11351676Sjpk * examine all entries, remove an old one if required, check 11361676Sjpk * if a new one needs to be added. 11371676Sjpk */ 11381676Sjpk if (stat(defpath, &dstat) == 0) { 11391676Sjpk if ((rc = _build_defattrs(dargs, &head_defent)) != 0) { 11401676Sjpk if (rc == 1) { 11411676Sjpk (void) close(tmpfd); 11421676Sjpk (void) unlink(tmpdefpath); 11431676Sjpk (void) close(lockfd); 11441676Sjpk return (rc); 11451676Sjpk } 11461676Sjpk } 11471676Sjpk } 11481676Sjpk /* 11491676Sjpk * write back any existing entries. 11501676Sjpk */ 11511676Sjpk _write_defattrs(tmpfp, head_defent); 11521676Sjpk 11531676Sjpk if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) { 11541676Sjpk /* add new entries */ 11551676Sjpk rc = _write_new_defattrs(tmpfp, dargs); 11561676Sjpk (void) fclose(tmpfp); 11571676Sjpk } else { 11581676Sjpk (void) fclose(tmpfp); 11591676Sjpk } 11601676Sjpk if (rename(tmpdefpath, defpath) != 0) { 11611676Sjpk rc = -1; 11621676Sjpk (void) unlink(tmpdefpath); 11631676Sjpk } 11641676Sjpk (void) close(lockfd); 11651676Sjpk 11661676Sjpk return (rc); 11671676Sjpk } 11681676Sjpk 11691676Sjpk /* 11701676Sjpk * da_update_device - 11711676Sjpk * writes devices entries to device_allocate and device_maps. 11721676Sjpk * returns 0 on success, -1 on error. 11731676Sjpk */ 11741676Sjpk int 11751676Sjpk da_update_device(da_args *dargs) 11761676Sjpk { 11771676Sjpk int rc; 11781676Sjpk int tafd = -1, tmfd = -1; 11791676Sjpk int lockfd = -1; 11801676Sjpk char *rootdir = NULL; 1181*4514Saj char *apathp = NULL, *mpathp = NULL; 1182*4514Saj char *dapathp = NULL, *dmpathp = NULL; 1183*4514Saj char apath[MAXPATHLEN], mpath[MAXPATHLEN]; 1184*4514Saj char dapath[MAXPATHLEN], dmpath[MAXPATHLEN]; 11851676Sjpk FILE *tafp = NULL, *tmfp = NULL, *dafp = NULL; 11861676Sjpk struct stat dastat; 11871676Sjpk devinfo_t *devinfo; 11881676Sjpk strentry_t *head_devmapp = NULL; 11891676Sjpk strentry_t *head_devallocp = NULL; 11901676Sjpk 11911676Sjpk if (dargs == NULL) 11921676Sjpk return (0); 11931676Sjpk 11941676Sjpk rootdir = dargs->rootdir; 11951676Sjpk devinfo = dargs->devinfo; 11961676Sjpk 11971676Sjpk /* 11981676Sjpk * adding/removing entries should be done in both 11991676Sjpk * device_allocate and device_maps. updates can be 12001676Sjpk * done in both or either of the files. 12011676Sjpk */ 12021676Sjpk if (dargs->optflag & DA_ADD || dargs->optflag & DA_REMOVE) { 12031676Sjpk if (dargs->optflag & DA_ALLOC_ONLY || 12041676Sjpk dargs->optflag & DA_MAPS_ONLY) 12051676Sjpk return (0); 12061676Sjpk } 12071676Sjpk 12081676Sjpk /* 12091676Sjpk * name, type and list are required fields for adding a new 12101676Sjpk * device. 12111676Sjpk */ 12121676Sjpk if ((dargs->optflag & DA_ADD) && 12131676Sjpk ((devinfo->devname == NULL) || 12141676Sjpk (devinfo->devtype == NULL) || 12151676Sjpk (devinfo->devlist == NULL))) { 12161676Sjpk return (-1); 12171676Sjpk } 12181676Sjpk 12191676Sjpk if (rootdir != NULL) { 12201676Sjpk if (snprintf(apath, sizeof (apath), "%s%s", rootdir, 12211676Sjpk TMPALLOC) >= sizeof (apath)) 12221676Sjpk return (-1); 12231676Sjpk apathp = apath; 12241676Sjpk if (snprintf(dapath, sizeof (dapath), "%s%s", rootdir, 12251676Sjpk DEVALLOC) >= sizeof (dapath)) 12261676Sjpk return (-1); 12271676Sjpk dapathp = dapath; 12281676Sjpk if (!(dargs->optflag & DA_ALLOC_ONLY)) { 12291676Sjpk if (snprintf(mpath, sizeof (mpath), "%s%s", rootdir, 12301676Sjpk TMPMAP) >= sizeof (mpath)) 12311676Sjpk return (-1); 12321676Sjpk mpathp = mpath; 12331676Sjpk if (snprintf(dmpath, sizeof (dmpath), "%s%s", rootdir, 12341676Sjpk DEVMAP) >= sizeof (dmpath)) 12351676Sjpk return (-1); 12361676Sjpk dmpathp = dmpath; 12371676Sjpk } 12381676Sjpk } else { 12391676Sjpk apathp = TMPALLOC; 12401676Sjpk dapathp = DEVALLOC; 12411676Sjpk mpathp = TMPMAP; 12421676Sjpk dmpathp = DEVMAP; 12431676Sjpk } 12441676Sjpk 12451676Sjpk if (dargs->optflag & DA_MAPS_ONLY) 12461676Sjpk goto dmap_only; 12471676Sjpk 12481676Sjpk /* 12491676Sjpk * Check if we are here just to record on/off status of 12501676Sjpk * device_allocation. 12511676Sjpk */ 12521676Sjpk if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) 12531676Sjpk lockfd = da_open_devdb(dargs->rootdir, &dafp, NULL, 12541676Sjpk DA_RDONLY|DA_ALLOC_ONLY); 12551676Sjpk else 12561676Sjpk lockfd = _da_lock_devdb(rootdir); 12571676Sjpk if (lockfd == -1) 12581676Sjpk return (-1); 12591676Sjpk 12601676Sjpk if ((tafd = open(apathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 12611676Sjpk (void) close(lockfd); 12621676Sjpk (void) fclose(dafp); 12631676Sjpk return (-1); 12641676Sjpk } 12651676Sjpk (void) fchown(tafd, DA_UID, DA_GID); 12661676Sjpk if ((tafp = fdopen(tafd, "r+")) == NULL) { 12671676Sjpk (void) close(tafd); 12681676Sjpk (void) unlink(apathp); 12691676Sjpk (void) fclose(dafp); 12701676Sjpk (void) close(lockfd); 12711676Sjpk return (-1); 12721676Sjpk } 12731676Sjpk 12741676Sjpk /* 12751676Sjpk * We don't need to parse the file if we are here just to record 12761676Sjpk * on/off status of device_allocation. 12771676Sjpk */ 12781676Sjpk if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) { 12791676Sjpk if (_record_on_off(dargs, tafp, dafp) == -1) { 12801676Sjpk (void) close(tafd); 12811676Sjpk (void) unlink(apathp); 12821676Sjpk (void) fclose(dafp); 12831676Sjpk (void) close(lockfd); 12841676Sjpk return (-1); 12851676Sjpk } 12861676Sjpk (void) fclose(dafp); 12871676Sjpk goto out; 12881676Sjpk } 12891676Sjpk 12901676Sjpk /* 12911676Sjpk * examine all the entries, remove an old one if forced to, 12921676Sjpk * and check that they are suitable for updating. 12931676Sjpk * we need to do this only if the file exists already. 12941676Sjpk */ 12951676Sjpk if (stat(dapathp, &dastat) == 0) { 12961676Sjpk if ((rc = _build_lists(dargs, &head_devallocp, 12971676Sjpk &head_devmapp)) != 0) { 12981676Sjpk if (rc != 1) { 12991676Sjpk (void) close(tafd); 13001676Sjpk (void) unlink(apathp); 13011676Sjpk (void) close(lockfd); 13021676Sjpk return (rc); 13031676Sjpk } 13041676Sjpk } 13051676Sjpk } 13061676Sjpk 13071676Sjpk /* 13081676Sjpk * write back any existing devalloc entries, along with 13091676Sjpk * the devalloc on/off string. 13101676Sjpk */ 13111676Sjpk _write_device_allocate(dapathp, tafp, head_devallocp); 13121676Sjpk 13131676Sjpk if (dargs->optflag & DA_ALLOC_ONLY) 13141676Sjpk goto out; 13151676Sjpk 13161676Sjpk dmap_only: 13171676Sjpk if ((tmfd = open(mpathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 13181676Sjpk (void) close(tafd); 13191676Sjpk (void) unlink(apathp); 13201676Sjpk (void) close(lockfd); 13211676Sjpk return (-1); 13221676Sjpk } 13231676Sjpk (void) fchown(tmfd, DA_UID, DA_GID); 13241676Sjpk if ((tmfp = fdopen(tmfd, "r+")) == NULL) { 13251676Sjpk (void) close(tafd); 13261676Sjpk (void) unlink(apathp); 13271676Sjpk (void) close(tmfd); 13281676Sjpk (void) unlink(mpathp); 13291676Sjpk (void) close(lockfd); 13301676Sjpk return (-1); 13311676Sjpk } 13321676Sjpk 13331676Sjpk /* write back any existing devmap entries */ 13341676Sjpk if (head_devmapp != NULL) 13351676Sjpk _write_device_maps(tmfp, head_devmapp); 13361676Sjpk 13371676Sjpk out: 13381676Sjpk if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) { 13391676Sjpk /* add any new entries */ 13401676Sjpk rc = _write_new_entry(tafp, dargs, DA_ALLOC_ONLY); 13411676Sjpk (void) fclose(tafp); 13421676Sjpk 13431676Sjpk if (rc == 0) 13441676Sjpk rc = _write_new_entry(tmfp, dargs, DA_MAPS_ONLY); 13451676Sjpk (void) fclose(tmfp); 13461676Sjpk } else { 13471676Sjpk if (tafp) 13481676Sjpk (void) fclose(tafp); 13491676Sjpk if (tmfp) 13501676Sjpk (void) fclose(tmfp); 13511676Sjpk } 13521676Sjpk 13531676Sjpk rc = 0; 13541676Sjpk if (!(dargs->optflag & DA_MAPS_ONLY)) { 13551676Sjpk if (rename(apathp, dapathp) != 0) { 13561676Sjpk rc = -1; 13571676Sjpk (void) unlink(apathp); 13581676Sjpk } 13591676Sjpk } 13601676Sjpk if (!(dargs->optflag & DA_ALLOC_ONLY)) { 13611676Sjpk if (rename(mpathp, dmpathp) != 0) { 13621676Sjpk rc = -1; 13631676Sjpk (void) unlink(mpathp); 13641676Sjpk } 13651676Sjpk } 13661676Sjpk 13671676Sjpk (void) close(lockfd); 13681676Sjpk 13691676Sjpk return (rc); 13701676Sjpk } 13711676Sjpk 13721676Sjpk /* 13731676Sjpk * da_add_list - 13741676Sjpk * adds new /dev link name to the linked list of devices. 13751676Sjpk * returns 0 if link added successfully, -1 on error. 13761676Sjpk */ 13771676Sjpk int 13781676Sjpk da_add_list(devlist_t *dlist, char *link, int new_instance, int flag) 13791676Sjpk { 13801676Sjpk int instance; 13811676Sjpk int nlen, plen; 13821676Sjpk int new_entry = 0; 13831676Sjpk char *dtype, *dexec, *tname, *kval; 13841676Sjpk char *minstr = NULL, *maxstr = NULL; 13851676Sjpk char dname[DA_MAXNAME]; 13861676Sjpk kva_t *kva; 13871676Sjpk deventry_t *dentry = NULL, *nentry = NULL, *pentry = NULL; 13881676Sjpk da_defs_t *da_defs; 13891676Sjpk 13901676Sjpk if (dlist == NULL || link == NULL) 13911676Sjpk return (-1); 13921676Sjpk 13931676Sjpk dname[0] = '\0'; 13941676Sjpk if (flag & DA_AUDIO) { 13951676Sjpk dentry = dlist->audio; 13961676Sjpk tname = DA_AUDIO_NAME; 13971676Sjpk dtype = DA_AUDIO_TYPE; 13981676Sjpk dexec = DA_DEFAULT_AUDIO_CLEAN; 13991676Sjpk } else if (flag & DA_CD) { 14001676Sjpk dentry = dlist->cd; 14011676Sjpk tname = DA_CD_NAME; 14021676Sjpk dtype = DA_CD_TYPE; 14031676Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 14041676Sjpk } else if (flag & DA_FLOPPY) { 14051676Sjpk dentry = dlist->floppy; 14061676Sjpk tname = DA_FLOPPY_NAME; 14071676Sjpk dtype = DA_FLOPPY_TYPE; 14081676Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 14091676Sjpk } else if (flag & DA_TAPE) { 14101676Sjpk dentry = dlist->tape; 14111676Sjpk tname = DA_TAPE_NAME; 14121676Sjpk dtype = DA_TAPE_TYPE; 14131676Sjpk dexec = DA_DEFAULT_TAPE_CLEAN; 14141676Sjpk } else if (flag & DA_RMDISK) { 14151676Sjpk dentry = dlist->rmdisk; 14161676Sjpk tname = DA_RMDISK_NAME; 14171676Sjpk dtype = DA_RMDISK_TYPE; 14181676Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 14191676Sjpk } else { 14201676Sjpk return (-1); 14211676Sjpk } 14221676Sjpk 14231676Sjpk for (nentry = dentry; nentry != NULL; nentry = nentry->next) { 14241676Sjpk pentry = nentry; 14251676Sjpk (void) sscanf(nentry->devinfo.devname, "%*[a-z]%d", &instance); 14261676Sjpk if (nentry->devinfo.instance == new_instance) 14271676Sjpk /* 14281676Sjpk * Add the new link name to the list of links 14291676Sjpk * that the device 'dname' has. 14301676Sjpk */ 14311676Sjpk break; 14321676Sjpk } 14331676Sjpk 14341676Sjpk if (nentry == NULL) { 14351676Sjpk /* 14361676Sjpk * Either this is the first entry ever, or no matching entry 14371676Sjpk * was found. Create a new one and add to the list. 14381676Sjpk */ 14391676Sjpk if (dentry == NULL) /* first entry ever */ 14401676Sjpk instance = 0; 14411676Sjpk else /* no matching entry */ 14421676Sjpk instance++; 14431676Sjpk (void) snprintf(dname, sizeof (dname), "%s%d", tname, instance); 14441676Sjpk if ((nentry = (deventry_t *)malloc(sizeof (deventry_t))) == 14451676Sjpk NULL) 14461676Sjpk return (-1); 14471676Sjpk if (pentry != NULL) 14481676Sjpk pentry->next = nentry; 14491676Sjpk new_entry = 1; 14501676Sjpk nentry->devinfo.devname = strdup(dname); 14511676Sjpk nentry->devinfo.devtype = dtype; 14521676Sjpk nentry->devinfo.devauths = DEFAULT_DEV_ALLOC_AUTH; 14531676Sjpk nentry->devinfo.devexec = dexec; 14541676Sjpk nentry->devinfo.instance = new_instance; 14551676Sjpk /* 14561676Sjpk * Look for default label range, authorizations and cleaning 14571676Sjpk * program in devalloc_defaults. If label range is not 14581676Sjpk * specified in devalloc_defaults, assume it to be admin_low 14591676Sjpk * to admin_high. 14601676Sjpk */ 14611676Sjpk minstr = DA_DEFAULT_MIN; 14621676Sjpk maxstr = DA_DEFAULT_MAX; 14631676Sjpk setdadefent(); 14641676Sjpk if (da_defs = getdadeftype(nentry->devinfo.devtype)) { 14651676Sjpk kva = da_defs->devopts; 14661676Sjpk if ((kval = kva_match(kva, DAOPT_MINLABEL)) != NULL) 14671676Sjpk minstr = strdup(kval); 14681676Sjpk if ((kval = kva_match(kva, DAOPT_MAXLABEL)) != NULL) 14691676Sjpk maxstr = strdup(kval); 14701676Sjpk if ((kval = kva_match(kva, DAOPT_AUTHS)) != NULL) 14711676Sjpk nentry->devinfo.devauths = strdup(kval); 14721676Sjpk if ((kval = kva_match(kva, DAOPT_CSCRIPT)) != NULL) 14731676Sjpk nentry->devinfo.devexec = strdup(kval); 14741676Sjpk freedadefent(da_defs); 14751676Sjpk } 14761676Sjpk enddadefent(); 14771676Sjpk kval = NULL; 14781676Sjpk nlen = strlen(DAOPT_MINLABEL) + strlen(KV_ASSIGN) + 14791676Sjpk strlen(minstr) + strlen(KV_TOKEN_DELIMIT) + 14801676Sjpk strlen(DAOPT_MAXLABEL) + strlen(KV_ASSIGN) + strlen(maxstr) 14811676Sjpk + 1; /* +1 for terminator */ 14821676Sjpk if (kval = (char *)malloc(nlen)) 14831676Sjpk (void) snprintf(kval, nlen, "%s%s%s%s%s%s%s", 14841676Sjpk DAOPT_MINLABEL, KV_ASSIGN, minstr, KV_TOKEN_DELIMIT, 14851676Sjpk DAOPT_MAXLABEL, KV_ASSIGN, maxstr); 14861676Sjpk nentry->devinfo.devopts = kval; 14871676Sjpk 14881676Sjpk nentry->devinfo.devlist = NULL; 14891676Sjpk nentry->next = NULL; 14901676Sjpk } 14911676Sjpk 14921676Sjpk nlen = strlen(link) + 1; /* +1 terminator */ 14931676Sjpk if (nentry->devinfo.devlist) { 14941676Sjpk plen = strlen(nentry->devinfo.devlist); 14951676Sjpk nlen = nlen + plen + 1; /* +1 for blank to separate entries */ 14961676Sjpk } else { 14971676Sjpk plen = 0; 14981676Sjpk } 14991676Sjpk 15001676Sjpk if ((nentry->devinfo.devlist = 15011676Sjpk (char *)realloc(nentry->devinfo.devlist, nlen)) == NULL) { 15021676Sjpk if (new_entry) { 15031676Sjpk nentry->devinfo.devname = NULL; 15041676Sjpk free(nentry->devinfo.devname); 15051676Sjpk nentry = NULL; 15061676Sjpk free(nentry); 15071676Sjpk if (pentry != NULL) 15081676Sjpk pentry->next = NULL; 15091676Sjpk } 15101676Sjpk return (-1); 15111676Sjpk } 15121676Sjpk 15131676Sjpk if (plen == 0) 15141676Sjpk (void) snprintf(nentry->devinfo.devlist, nlen, "%s", link); 15151676Sjpk else 15161676Sjpk (void) snprintf(nentry->devinfo.devlist + plen, nlen - plen, 15171676Sjpk " %s", link); 15181676Sjpk 15191676Sjpk if (pentry == NULL) { 15201676Sjpk /* 15211676Sjpk * This is the first entry of this device type. 15221676Sjpk */ 15231676Sjpk if (flag & DA_AUDIO) 15241676Sjpk dlist->audio = nentry; 15251676Sjpk else if (flag & DA_CD) 15261676Sjpk dlist->cd = nentry; 15271676Sjpk else if (flag & DA_FLOPPY) 15281676Sjpk dlist->floppy = nentry; 15291676Sjpk else if (flag & DA_TAPE) 15301676Sjpk dlist->tape = nentry; 15311676Sjpk else if (flag & DA_RMDISK) 15321676Sjpk dlist->rmdisk = nentry; 15331676Sjpk } 15341676Sjpk 15351676Sjpk return (0); 15361676Sjpk } 15371676Sjpk 15381676Sjpk /* 15391676Sjpk * da_remove_list - 15401676Sjpk * removes a /dev link name from the linked list of devices. 15411676Sjpk * returns type of device if link for that device removed 15421676Sjpk * successfully, else returns -1 on error. 15431676Sjpk * if all links for a device are removed, stores that device 15441676Sjpk * name in devname. 15451676Sjpk */ 15461676Sjpk int 15471676Sjpk da_remove_list(devlist_t *dlist, char *link, int type, char *devname, int size) 15481676Sjpk { 15491676Sjpk int flag; 15501676Sjpk int remove_dev = 0; 15511676Sjpk int nlen, plen, slen; 15521676Sjpk char *lasts, *lname, *oldlist; 15531676Sjpk struct stat rmstat; 15541676Sjpk deventry_t *dentry, *current, *prev; 15551676Sjpk 15561676Sjpk if (type != NULL) 15571676Sjpk flag = type; 15581676Sjpk else if (link == NULL) 15591676Sjpk return (-1); 15601676Sjpk else if (strstr(link, DA_AUDIO_NAME) || strstr(link, DA_SOUND_NAME)) 15611676Sjpk flag = DA_AUDIO; 15621676Sjpk else if (strstr(link, "dsk") || strstr(link, "rdsk") || 15631676Sjpk strstr(link, "sr") || strstr(link, "rsr")) 15641676Sjpk flag = DA_CD; 15651676Sjpk else if (strstr(link, "fd") || strstr(link, "rfd") || 15661676Sjpk strstr(link, "diskette") || strstr(link, "rdiskette")) 15671676Sjpk flag = DA_FLOPPY; 15681676Sjpk else if (strstr(link, DA_TAPE_NAME)) 15691676Sjpk flag = DA_TAPE; 15701676Sjpk else 15711676Sjpk flag = DA_RMDISK; 15721676Sjpk 15731676Sjpk switch (type) { 15741676Sjpk case DA_AUDIO: 15751676Sjpk dentry = dlist->audio; 15761676Sjpk break; 15771676Sjpk case DA_CD: 15781676Sjpk dentry = dlist->cd; 15791676Sjpk break; 15801676Sjpk case DA_FLOPPY: 15811676Sjpk dentry = dlist->floppy; 15821676Sjpk break; 15831676Sjpk case DA_TAPE: 15841676Sjpk dentry = dlist->tape; 15851676Sjpk break; 15861676Sjpk case DA_RMDISK: 15871676Sjpk dentry = dlist->rmdisk; 15881676Sjpk break; 15891676Sjpk default: 15901676Sjpk return (-1); 15911676Sjpk } 15921676Sjpk 15931676Sjpk if ((type != NULL) && (link == NULL)) { 15941676Sjpk for (current = dentry, prev = dentry; current != NULL; 15951676Sjpk current = current->next) { 15961676Sjpk oldlist = strdup(current->devinfo.devlist); 15971676Sjpk for (lname = strtok_r(oldlist, " ", &lasts); 15981676Sjpk lname != NULL; 15991676Sjpk lname = strtok_r(NULL, " ", &lasts)) { 16001676Sjpk if (stat(lname, &rmstat) != 0) { 16011676Sjpk remove_dev = 1; 16021676Sjpk goto remove_dev; 16031676Sjpk } 16041676Sjpk } 16051676Sjpk prev = current; 16061676Sjpk } 16071676Sjpk return (-1); 16081676Sjpk } 16091676Sjpk 16101676Sjpk for (current = dentry, prev = dentry; current != NULL; 16111676Sjpk current = current->next) { 16121676Sjpk plen = strlen(current->devinfo.devlist); 16131676Sjpk nlen = strlen(link); 16141676Sjpk if (plen == nlen) { 16151676Sjpk if (strcmp(current->devinfo.devlist, link) == 0) { 16161676Sjpk /* last name in the list */ 16171676Sjpk remove_dev = 1; 16181676Sjpk break; 16191676Sjpk } 16201676Sjpk } 16211676Sjpk if (strstr(current->devinfo.devlist, link)) { 16221676Sjpk nlen = plen - nlen + 1; 16231676Sjpk oldlist = strdup(current->devinfo.devlist); 16241676Sjpk if ((current->devinfo.devlist = 16251676Sjpk (char *)realloc(current->devinfo.devlist, 16261676Sjpk nlen)) == NULL) { 16271676Sjpk free(oldlist); 16281676Sjpk return (-1); 16291676Sjpk } 16301676Sjpk current->devinfo.devlist[0] = '\0'; 16311676Sjpk nlen = plen = slen = 0; 16321676Sjpk for (lname = strtok_r(oldlist, " ", &lasts); 16331676Sjpk lname != NULL; 16341676Sjpk lname = strtok_r(NULL, " ", &lasts)) { 16351676Sjpk if (strcmp(lname, link) == 0) 16361676Sjpk continue; 16371676Sjpk nlen = strlen(lname) + plen + 1; 16381676Sjpk if (plen == 0) { 16391676Sjpk slen = 16401676Sjpk snprintf(current->devinfo.devlist, 1641*4514Saj nlen, "%s", lname); 16421676Sjpk } else { 16431676Sjpk slen = 16441676Sjpk snprintf(current->devinfo.devlist + 1645*4514Saj plen, nlen - plen, " %s", lname); 16461676Sjpk } 16471676Sjpk plen = plen + slen + 1; 16481676Sjpk } 16491676Sjpk free(oldlist); 16501676Sjpk break; 16511676Sjpk } 16521676Sjpk prev = current; 16531676Sjpk } 16541676Sjpk 16551676Sjpk remove_dev: 16561676Sjpk if (remove_dev == 1) { 16571676Sjpk (void) strlcpy(devname, current->devinfo.devname, size); 16581676Sjpk free(current->devinfo.devname); 16591676Sjpk free(current->devinfo.devlist); 16601676Sjpk current->devinfo.devname = current->devinfo.devlist = NULL; 16611676Sjpk prev->next = current->next; 16621676Sjpk free(current); 16631676Sjpk current = NULL; 16641676Sjpk } 16651676Sjpk if ((remove_dev == 1) && (prev->devinfo.devname == NULL)) { 16661676Sjpk if (prev->next) { 16671676Sjpk /* 16681676Sjpk * what we removed above was the first entry 16691676Sjpk * in the list. make the next entry to be the 16701676Sjpk * first. 16711676Sjpk */ 16721676Sjpk current = prev->next; 16731676Sjpk } else { 16741676Sjpk /* 16751676Sjpk * the matching entry was the only entry in the list 16761676Sjpk * for this type. 16771676Sjpk */ 16781676Sjpk current = NULL; 16791676Sjpk } 16801676Sjpk if (flag & DA_AUDIO) 16811676Sjpk dlist->audio = current; 16821676Sjpk else if (flag & DA_CD) 16831676Sjpk dlist->cd = current; 16841676Sjpk else if (flag & DA_FLOPPY) 16851676Sjpk dlist->floppy = current; 16861676Sjpk else if (flag & DA_TAPE) 16871676Sjpk dlist->tape = current; 16881676Sjpk else if (flag & DA_RMDISK) 16891676Sjpk dlist->rmdisk = current; 16901676Sjpk } 16911676Sjpk 16921676Sjpk return (flag); 16931676Sjpk } 16941676Sjpk 16951676Sjpk /* 16961676Sjpk * da_is_on - 16971676Sjpk * checks if device allocation feature is turned on. 16981676Sjpk * returns 1 if on, 0 if off, -1 if status string not 16991676Sjpk * found in device_allocate. 17001676Sjpk */ 17011676Sjpk int 17021676Sjpk da_is_on() 17031676Sjpk { 17041676Sjpk return (getdaon()); 17051676Sjpk } 17061676Sjpk 17071676Sjpk /* 17081676Sjpk * da_print_device - 17091676Sjpk * debug routine to print device entries. 17101676Sjpk */ 17111676Sjpk void 17121676Sjpk da_print_device(int flag, devlist_t *devlist) 17131676Sjpk { 17141676Sjpk deventry_t *entry, *dentry; 17151676Sjpk devinfo_t *devinfo; 17161676Sjpk 17171676Sjpk if (flag & DA_AUDIO) 17181676Sjpk dentry = devlist->audio; 17191676Sjpk else if (flag & DA_CD) 17201676Sjpk dentry = devlist->cd; 17211676Sjpk else if (flag & DA_FLOPPY) 17221676Sjpk dentry = devlist->floppy; 17231676Sjpk else if (flag & DA_TAPE) 17241676Sjpk dentry = devlist->tape; 17251676Sjpk else if (flag & DA_RMDISK) 17261676Sjpk dentry = devlist->rmdisk; 17271676Sjpk else 17281676Sjpk return; 17291676Sjpk 17301676Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 17311676Sjpk devinfo = &(entry->devinfo); 17321676Sjpk (void) fprintf(stdout, "name: %s\n", devinfo->devname); 17331676Sjpk (void) fprintf(stdout, "type: %s\n", devinfo->devtype); 17341676Sjpk (void) fprintf(stdout, "auth: %s\n", devinfo->devauths); 17351676Sjpk (void) fprintf(stdout, "exec: %s\n", devinfo->devexec); 17361676Sjpk (void) fprintf(stdout, "list: %s\n\n", devinfo->devlist); 17371676Sjpk } 17381676Sjpk } 1739