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 /* 231676Sjpk * Copyright 2006 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 } 100*1914Scasper 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); 206*1914Scasper 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; 8521676Sjpk char *lockfile; 8531676Sjpk char path[MAXPATHLEN]; 8541676Sjpk int size = sizeof (path); 8551676Sjpk 8561676Sjpk if (rootdir == NULL) { 8571676Sjpk lockfile = DA_DB_LOCK; 8581676Sjpk } else { 8591676Sjpk path[0] = '\0'; 8601676Sjpk if (snprintf(path, size, "%s%s", rootdir, DA_DB_LOCK) >= size) 8611676Sjpk return (-1); 8621676Sjpk lockfile = path; 8631676Sjpk } 8641676Sjpk 8651676Sjpk if ((lockfd = open(lockfile, O_RDWR | O_CREAT, 0600)) == -1) 8661676Sjpk /* cannot open lock file */ 8671676Sjpk return (-1); 8681676Sjpk 8691676Sjpk (void) fchown(lockfd, DA_UID, DA_GID); 8701676Sjpk 8711676Sjpk if (lseek(lockfd, (off_t)0, SEEK_SET) == -1) { 8721676Sjpk /* cannot position lock file */ 8731676Sjpk (void) close(lockfd); 8741676Sjpk return (-1); 8751676Sjpk } 8761676Sjpk if (lockf(lockfd, F_TLOCK, 0) == -1) { 8771676Sjpk /* cannot set lock */ 8781676Sjpk (void) close(lockfd); 8791676Sjpk return (-1); 8801676Sjpk } 8811676Sjpk (void) utime(lockfile, NULL); 8821676Sjpk 8831676Sjpk return (lockfd); 8841676Sjpk } 8851676Sjpk 8861676Sjpk /* 8871676Sjpk * da_open_devdb - 8881676Sjpk * opens one or both database files - device_allocate, device_maps - in 8891676Sjpk * the specified mode. 8901676Sjpk * locks the database files; lock is either broken explicitly by the 8911676Sjpk * caller by closing the lock file fd, or it expires automatically at 8921676Sjpk * process termination. 8931676Sjpk * writes the file pointer of opened file in the input args - dafp, dmfp. 8941676Sjpk * returns fd of the lock file on success, -2 if database file does not 8951676Sjpk * exist, -1 on other errors. 8961676Sjpk */ 8971676Sjpk int 8981676Sjpk da_open_devdb(char *rootdir, FILE **dafp, FILE **dmfp, int flag) 8991676Sjpk { 9001676Sjpk int oflag = 0; 9011676Sjpk int fda = -1; 9021676Sjpk int fdm = -1; 9031676Sjpk int lockfd = -1; 9041676Sjpk char *fname; 9051676Sjpk char *fmode; 9061676Sjpk char path[MAXPATHLEN]; 9071676Sjpk FILE *devfile; 9081676Sjpk 9091676Sjpk if ((dafp == NULL) && (dmfp == NULL)) 9101676Sjpk return (-1); 9111676Sjpk 9121676Sjpk if (flag & DA_RDWR) { 9131676Sjpk oflag = DA_RDWR; 914*1914Scasper fmode = "r+F"; 9151676Sjpk } else if (flag & DA_RDONLY) { 9161676Sjpk oflag = DA_RDONLY; 917*1914Scasper fmode = "rF"; 9181676Sjpk } 9191676Sjpk 9201676Sjpk if ((lockfd = _da_lock_devdb(rootdir)) == -1) 9211676Sjpk return (-1); 9221676Sjpk 9231676Sjpk if ((dafp == NULL) || (flag & DA_MAPS_ONLY)) 9241676Sjpk goto dmap_only; 9251676Sjpk 9261676Sjpk path[0] = '\0'; 9271676Sjpk 9281676Sjpk /* 9291676Sjpk * open the device allocation file 9301676Sjpk */ 9311676Sjpk if (rootdir == NULL) { 9321676Sjpk fname = DEVALLOC; 9331676Sjpk } else { 9341676Sjpk if (snprintf(path, sizeof (path), "%s%s", rootdir, 9351676Sjpk DEVALLOC) >= sizeof (path)) { 9361676Sjpk if (lockfd != -1) 9371676Sjpk (void) close(lockfd); 9381676Sjpk return (-1); 9391676Sjpk } 9401676Sjpk fname = path; 9411676Sjpk } 9421676Sjpk if ((fda = open(fname, oflag, DA_DBMODE)) == -1) { 9431676Sjpk if (lockfd != -1) 9441676Sjpk (void) close(lockfd); 9451676Sjpk return ((errno == ENOENT) ? -2 : -1); 9461676Sjpk } 9471676Sjpk if ((devfile = fdopen(fda, fmode)) == NULL) { 9481676Sjpk (void) close(fda); 9491676Sjpk if (lockfd != -1) 9501676Sjpk (void) close(lockfd); 9511676Sjpk return (-1); 9521676Sjpk } 9531676Sjpk *dafp = devfile; 9541676Sjpk (void) fchmod(fda, DA_DBMODE); 9551676Sjpk 9561676Sjpk if ((flag & DA_ALLOC_ONLY)) 9571676Sjpk goto out; 9581676Sjpk 9591676Sjpk dmap_only: 9601676Sjpk path[0] = '\0'; 9611676Sjpk /* 9621676Sjpk * open the device map file 9631676Sjpk */ 9641676Sjpk if (rootdir == NULL) { 9651676Sjpk fname = DEVMAP; 9661676Sjpk } else { 9671676Sjpk if (snprintf(path, sizeof (path), "%s%s", rootdir, 9681676Sjpk DEVMAP) >= sizeof (path)) { 9691676Sjpk (void) close(fda); 9701676Sjpk if (lockfd != -1) 9711676Sjpk (void) close(lockfd); 9721676Sjpk return (-1); 9731676Sjpk } 9741676Sjpk fname = path; 9751676Sjpk } 9761676Sjpk 9771676Sjpk if ((fdm = open(fname, oflag, DA_DBMODE)) == -1) { 9781676Sjpk if (lockfd != -1) 9791676Sjpk (void) close(lockfd); 9801676Sjpk return ((errno == ENOENT) ? -2 : -1); 9811676Sjpk } 9821676Sjpk 9831676Sjpk if ((devfile = fdopen(fdm, fmode)) == NULL) { 9841676Sjpk (void) close(fdm); 9851676Sjpk (void) close(fda); 9861676Sjpk if (lockfd != -1) 9871676Sjpk (void) close(lockfd); 9881676Sjpk return (-1); 9891676Sjpk } 9901676Sjpk *dmfp = devfile; 9911676Sjpk (void) fchmod(fdm, DA_DBMODE); 9921676Sjpk 9931676Sjpk out: 9941676Sjpk return (lockfd); 9951676Sjpk } 9961676Sjpk 9971676Sjpk /* 9981676Sjpk * _record_on_off - 9991676Sjpk * adds either DA_ON_STR or DA_OFF_STR to device_allocate 10001676Sjpk * returns 0 on success, -1 on error. 10011676Sjpk */ 10021676Sjpk static int 10031676Sjpk _record_on_off(da_args *dargs, FILE *tafp, FILE *dafp) 10041676Sjpk { 10051676Sjpk int dafd; 10061676Sjpk int nsize; 10071676Sjpk int nitems = 1; 10081676Sjpk int actionlen; 10091676Sjpk int str_found = 0; 10101676Sjpk int len = 0, nlen = 0, plen = 0; 10111676Sjpk char *ptr = NULL; 10121676Sjpk char *actionstr; 10131676Sjpk char *nbuf = NULL; 10141676Sjpk char line[MAX_CANON]; 10151676Sjpk struct stat dastat; 10161676Sjpk 10171676Sjpk if (dargs->optflag & DA_ON) 10181676Sjpk actionstr = DA_ON_STR; 10191676Sjpk else 10201676Sjpk actionstr = DA_OFF_STR; 10211676Sjpk actionlen = strlen(actionstr); 10221676Sjpk dafd = fileno(dafp); 10231676Sjpk if (fstat(dafd, &dastat) == -1) 10241676Sjpk return (-1); 10251676Sjpk 10261676Sjpk /* check the old device_allocate for on/off string */ 10271676Sjpk ptr = fgets(line, MAX_CANON, dafp); 10281676Sjpk if (ptr != NULL) { 10291676Sjpk if ((strcmp(line, DA_ON_STR) == 0) || 10301676Sjpk (strcmp(line, DA_OFF_STR) == 0)) { 10311676Sjpk str_found = 1; 10321676Sjpk nsize = dastat.st_size; 10331676Sjpk } 10341676Sjpk } 10351676Sjpk if (!ptr || !str_found) { 10361676Sjpk /* 10371676Sjpk * the file never had either the on or the off string; 10381676Sjpk * make room for it. 10391676Sjpk */ 10401676Sjpk str_found = 0; 10411676Sjpk nsize = dastat.st_size + actionlen + 1; 10421676Sjpk } 10431676Sjpk if ((nbuf = (char *)malloc(nsize)) == NULL) 10441676Sjpk return (-1); 10451676Sjpk nbuf[0] = '\0'; 10461676Sjpk /* put the on/off string */ 10471676Sjpk (void) strcpy(nbuf, actionstr); 10481676Sjpk nlen = strlen(nbuf); 10491676Sjpk plen = nlen; 10501676Sjpk if (ptr && !str_found) { 10511676Sjpk /* now put the first line that we read in fgets */ 10521676Sjpk nlen = plen + strlen(line) + 1; 10531676Sjpk len = snprintf(nbuf + plen, nlen - plen, "%s", line); 10541676Sjpk if (len >= nsize) { 10551676Sjpk free(nbuf); 10561676Sjpk return (-1); 10571676Sjpk } 10581676Sjpk plen += len; 10591676Sjpk } 10601676Sjpk 10611676Sjpk /* now get the rest of the old file */ 10621676Sjpk while (fgets(line, MAX_CANON, dafp) != NULL) { 10631676Sjpk nlen = plen + strlen(line) + 1; 10641676Sjpk len = snprintf(nbuf + plen, nlen - plen, "%s", line); 10651676Sjpk if (len >= nsize) { 10661676Sjpk free(nbuf); 10671676Sjpk return (-1); 10681676Sjpk } 10691676Sjpk plen += len; 10701676Sjpk } 10711676Sjpk len = strlen(nbuf) + 1; 10721676Sjpk if (len < nsize) 10731676Sjpk nbuf[len] = '\n'; 10741676Sjpk 10751676Sjpk /* write the on/off str + the old device_allocate to the temp file */ 10761676Sjpk if (fwrite(nbuf, nsize, nitems, tafp) < nitems) { 10771676Sjpk free(nbuf); 10781676Sjpk return (-1); 10791676Sjpk } 10801676Sjpk 10811676Sjpk free(nbuf); 10821676Sjpk 10831676Sjpk return (0); 10841676Sjpk } 10851676Sjpk 10861676Sjpk /* 10871676Sjpk * da_update_defattrs - 10881676Sjpk * writes default attributes to devalloc_defaults 10891676Sjpk * returns 0 on success, -1 on error. 10901676Sjpk */ 10911676Sjpk int 10921676Sjpk da_update_defattrs(da_args *dargs) 10931676Sjpk { 10941676Sjpk int rc = 0, lockfd = 0, tmpfd = 0; 10951676Sjpk char *defpath = DEFATTRS; 10961676Sjpk char *tmpdefpath = TMPATTRS; 10971676Sjpk FILE *tmpfp = NULL; 10981676Sjpk struct stat dstat; 10991676Sjpk strentry_t *head_defent = NULL; 11001676Sjpk 11011676Sjpk if (dargs == NULL) 11021676Sjpk return (0); 11031676Sjpk if ((lockfd = _da_lock_devdb(NULL)) == -1) 11041676Sjpk return (-1); 11051676Sjpk if ((tmpfd = open(tmpdefpath, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 11061676Sjpk (void) close(lockfd); 11071676Sjpk return (-1); 11081676Sjpk } 11091676Sjpk (void) fchown(tmpfd, DA_UID, DA_GID); 11101676Sjpk if ((tmpfp = fdopen(tmpfd, "r+")) == NULL) { 11111676Sjpk (void) close(tmpfd); 11121676Sjpk (void) unlink(tmpdefpath); 11131676Sjpk (void) close(lockfd); 11141676Sjpk return (-1); 11151676Sjpk } 11161676Sjpk /* 11171676Sjpk * examine all entries, remove an old one if required, check 11181676Sjpk * if a new one needs to be added. 11191676Sjpk */ 11201676Sjpk if (stat(defpath, &dstat) == 0) { 11211676Sjpk if ((rc = _build_defattrs(dargs, &head_defent)) != 0) { 11221676Sjpk if (rc == 1) { 11231676Sjpk (void) close(tmpfd); 11241676Sjpk (void) unlink(tmpdefpath); 11251676Sjpk (void) close(lockfd); 11261676Sjpk return (rc); 11271676Sjpk } 11281676Sjpk } 11291676Sjpk } 11301676Sjpk /* 11311676Sjpk * write back any existing entries. 11321676Sjpk */ 11331676Sjpk _write_defattrs(tmpfp, head_defent); 11341676Sjpk 11351676Sjpk if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) { 11361676Sjpk /* add new entries */ 11371676Sjpk rc = _write_new_defattrs(tmpfp, dargs); 11381676Sjpk (void) fclose(tmpfp); 11391676Sjpk } else { 11401676Sjpk (void) fclose(tmpfp); 11411676Sjpk } 11421676Sjpk if (rename(tmpdefpath, defpath) != 0) { 11431676Sjpk rc = -1; 11441676Sjpk (void) unlink(tmpdefpath); 11451676Sjpk } 11461676Sjpk (void) close(lockfd); 11471676Sjpk 11481676Sjpk return (rc); 11491676Sjpk } 11501676Sjpk 11511676Sjpk /* 11521676Sjpk * da_update_device - 11531676Sjpk * writes devices entries to device_allocate and device_maps. 11541676Sjpk * returns 0 on success, -1 on error. 11551676Sjpk */ 11561676Sjpk int 11571676Sjpk da_update_device(da_args *dargs) 11581676Sjpk { 11591676Sjpk int rc; 11601676Sjpk int tafd = -1, tmfd = -1; 11611676Sjpk int lockfd = -1; 11621676Sjpk char *rootdir = NULL; 11631676Sjpk char *apathp = NULL, *mpathp = NULL, *dapathp = NULL, 11641676Sjpk *dmpathp = NULL; 11651676Sjpk char apath[MAXPATHLEN], mpath[MAXPATHLEN], 11661676Sjpk dapath[MAXPATHLEN], dmpath[MAXPATHLEN]; 11671676Sjpk FILE *tafp = NULL, *tmfp = NULL, *dafp = NULL; 11681676Sjpk struct stat dastat; 11691676Sjpk devinfo_t *devinfo; 11701676Sjpk strentry_t *head_devmapp = NULL; 11711676Sjpk strentry_t *head_devallocp = NULL; 11721676Sjpk 11731676Sjpk if (dargs == NULL) 11741676Sjpk return (0); 11751676Sjpk 11761676Sjpk rootdir = dargs->rootdir; 11771676Sjpk devinfo = dargs->devinfo; 11781676Sjpk 11791676Sjpk /* 11801676Sjpk * adding/removing entries should be done in both 11811676Sjpk * device_allocate and device_maps. updates can be 11821676Sjpk * done in both or either of the files. 11831676Sjpk */ 11841676Sjpk if (dargs->optflag & DA_ADD || dargs->optflag & DA_REMOVE) { 11851676Sjpk if (dargs->optflag & DA_ALLOC_ONLY || 11861676Sjpk dargs->optflag & DA_MAPS_ONLY) 11871676Sjpk return (0); 11881676Sjpk } 11891676Sjpk 11901676Sjpk /* 11911676Sjpk * name, type and list are required fields for adding a new 11921676Sjpk * device. 11931676Sjpk */ 11941676Sjpk if ((dargs->optflag & DA_ADD) && 11951676Sjpk ((devinfo->devname == NULL) || 11961676Sjpk (devinfo->devtype == NULL) || 11971676Sjpk (devinfo->devlist == NULL))) { 11981676Sjpk return (-1); 11991676Sjpk } 12001676Sjpk 12011676Sjpk if (rootdir != NULL) { 12021676Sjpk if (snprintf(apath, sizeof (apath), "%s%s", rootdir, 12031676Sjpk TMPALLOC) >= sizeof (apath)) 12041676Sjpk return (-1); 12051676Sjpk apathp = apath; 12061676Sjpk if (snprintf(dapath, sizeof (dapath), "%s%s", rootdir, 12071676Sjpk DEVALLOC) >= sizeof (dapath)) 12081676Sjpk return (-1); 12091676Sjpk dapathp = dapath; 12101676Sjpk if (!(dargs->optflag & DA_ALLOC_ONLY)) { 12111676Sjpk if (snprintf(mpath, sizeof (mpath), "%s%s", rootdir, 12121676Sjpk TMPMAP) >= sizeof (mpath)) 12131676Sjpk return (-1); 12141676Sjpk mpathp = mpath; 12151676Sjpk if (snprintf(dmpath, sizeof (dmpath), "%s%s", rootdir, 12161676Sjpk DEVMAP) >= sizeof (dmpath)) 12171676Sjpk return (-1); 12181676Sjpk dmpathp = dmpath; 12191676Sjpk } 12201676Sjpk } else { 12211676Sjpk apathp = TMPALLOC; 12221676Sjpk dapathp = DEVALLOC; 12231676Sjpk mpathp = TMPMAP; 12241676Sjpk dmpathp = DEVMAP; 12251676Sjpk } 12261676Sjpk 12271676Sjpk if (dargs->optflag & DA_MAPS_ONLY) 12281676Sjpk goto dmap_only; 12291676Sjpk 12301676Sjpk /* 12311676Sjpk * Check if we are here just to record on/off status of 12321676Sjpk * device_allocation. 12331676Sjpk */ 12341676Sjpk if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) 12351676Sjpk lockfd = da_open_devdb(dargs->rootdir, &dafp, NULL, 12361676Sjpk DA_RDONLY|DA_ALLOC_ONLY); 12371676Sjpk else 12381676Sjpk lockfd = _da_lock_devdb(rootdir); 12391676Sjpk if (lockfd == -1) 12401676Sjpk return (-1); 12411676Sjpk 12421676Sjpk if ((tafd = open(apathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 12431676Sjpk (void) close(lockfd); 12441676Sjpk (void) fclose(dafp); 12451676Sjpk return (-1); 12461676Sjpk } 12471676Sjpk (void) fchown(tafd, DA_UID, DA_GID); 12481676Sjpk if ((tafp = fdopen(tafd, "r+")) == NULL) { 12491676Sjpk (void) close(tafd); 12501676Sjpk (void) unlink(apathp); 12511676Sjpk (void) fclose(dafp); 12521676Sjpk (void) close(lockfd); 12531676Sjpk return (-1); 12541676Sjpk } 12551676Sjpk 12561676Sjpk /* 12571676Sjpk * We don't need to parse the file if we are here just to record 12581676Sjpk * on/off status of device_allocation. 12591676Sjpk */ 12601676Sjpk if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) { 12611676Sjpk if (_record_on_off(dargs, tafp, dafp) == -1) { 12621676Sjpk (void) close(tafd); 12631676Sjpk (void) unlink(apathp); 12641676Sjpk (void) fclose(dafp); 12651676Sjpk (void) close(lockfd); 12661676Sjpk return (-1); 12671676Sjpk } 12681676Sjpk (void) fclose(dafp); 12691676Sjpk goto out; 12701676Sjpk } 12711676Sjpk 12721676Sjpk /* 12731676Sjpk * examine all the entries, remove an old one if forced to, 12741676Sjpk * and check that they are suitable for updating. 12751676Sjpk * we need to do this only if the file exists already. 12761676Sjpk */ 12771676Sjpk if (stat(dapathp, &dastat) == 0) { 12781676Sjpk if ((rc = _build_lists(dargs, &head_devallocp, 12791676Sjpk &head_devmapp)) != 0) { 12801676Sjpk if (rc != 1) { 12811676Sjpk (void) close(tafd); 12821676Sjpk (void) unlink(apathp); 12831676Sjpk (void) close(lockfd); 12841676Sjpk return (rc); 12851676Sjpk } 12861676Sjpk } 12871676Sjpk } 12881676Sjpk 12891676Sjpk /* 12901676Sjpk * write back any existing devalloc entries, along with 12911676Sjpk * the devalloc on/off string. 12921676Sjpk */ 12931676Sjpk _write_device_allocate(dapathp, tafp, head_devallocp); 12941676Sjpk 12951676Sjpk if (dargs->optflag & DA_ALLOC_ONLY) 12961676Sjpk goto out; 12971676Sjpk 12981676Sjpk dmap_only: 12991676Sjpk if ((tmfd = open(mpathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 13001676Sjpk (void) close(tafd); 13011676Sjpk (void) unlink(apathp); 13021676Sjpk (void) close(lockfd); 13031676Sjpk return (-1); 13041676Sjpk } 13051676Sjpk (void) fchown(tmfd, DA_UID, DA_GID); 13061676Sjpk if ((tmfp = fdopen(tmfd, "r+")) == NULL) { 13071676Sjpk (void) close(tafd); 13081676Sjpk (void) unlink(apathp); 13091676Sjpk (void) close(tmfd); 13101676Sjpk (void) unlink(mpathp); 13111676Sjpk (void) close(lockfd); 13121676Sjpk return (-1); 13131676Sjpk } 13141676Sjpk 13151676Sjpk /* write back any existing devmap entries */ 13161676Sjpk if (head_devmapp != NULL) 13171676Sjpk _write_device_maps(tmfp, head_devmapp); 13181676Sjpk 13191676Sjpk out: 13201676Sjpk if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) { 13211676Sjpk /* add any new entries */ 13221676Sjpk rc = _write_new_entry(tafp, dargs, DA_ALLOC_ONLY); 13231676Sjpk (void) fclose(tafp); 13241676Sjpk 13251676Sjpk if (rc == 0) 13261676Sjpk rc = _write_new_entry(tmfp, dargs, DA_MAPS_ONLY); 13271676Sjpk (void) fclose(tmfp); 13281676Sjpk } else { 13291676Sjpk if (tafp) 13301676Sjpk (void) fclose(tafp); 13311676Sjpk if (tmfp) 13321676Sjpk (void) fclose(tmfp); 13331676Sjpk } 13341676Sjpk 13351676Sjpk rc = 0; 13361676Sjpk if (!(dargs->optflag & DA_MAPS_ONLY)) { 13371676Sjpk if (rename(apathp, dapathp) != 0) { 13381676Sjpk rc = -1; 13391676Sjpk (void) unlink(apathp); 13401676Sjpk } 13411676Sjpk } 13421676Sjpk if (!(dargs->optflag & DA_ALLOC_ONLY)) { 13431676Sjpk if (rename(mpathp, dmpathp) != 0) { 13441676Sjpk rc = -1; 13451676Sjpk (void) unlink(mpathp); 13461676Sjpk } 13471676Sjpk } 13481676Sjpk 13491676Sjpk (void) close(lockfd); 13501676Sjpk 13511676Sjpk return (rc); 13521676Sjpk } 13531676Sjpk 13541676Sjpk /* 13551676Sjpk * da_add_list - 13561676Sjpk * adds new /dev link name to the linked list of devices. 13571676Sjpk * returns 0 if link added successfully, -1 on error. 13581676Sjpk */ 13591676Sjpk int 13601676Sjpk da_add_list(devlist_t *dlist, char *link, int new_instance, int flag) 13611676Sjpk { 13621676Sjpk int instance; 13631676Sjpk int nlen, plen; 13641676Sjpk int new_entry = 0; 13651676Sjpk char *dtype, *dexec, *tname, *kval; 13661676Sjpk char *minstr = NULL, *maxstr = NULL; 13671676Sjpk char dname[DA_MAXNAME]; 13681676Sjpk kva_t *kva; 13691676Sjpk deventry_t *dentry = NULL, *nentry = NULL, *pentry = NULL; 13701676Sjpk da_defs_t *da_defs; 13711676Sjpk 13721676Sjpk if (dlist == NULL || link == NULL) 13731676Sjpk return (-1); 13741676Sjpk 13751676Sjpk dname[0] = '\0'; 13761676Sjpk if (flag & DA_AUDIO) { 13771676Sjpk dentry = dlist->audio; 13781676Sjpk tname = DA_AUDIO_NAME; 13791676Sjpk dtype = DA_AUDIO_TYPE; 13801676Sjpk dexec = DA_DEFAULT_AUDIO_CLEAN; 13811676Sjpk } else if (flag & DA_CD) { 13821676Sjpk dentry = dlist->cd; 13831676Sjpk tname = DA_CD_NAME; 13841676Sjpk dtype = DA_CD_TYPE; 13851676Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 13861676Sjpk } else if (flag & DA_FLOPPY) { 13871676Sjpk dentry = dlist->floppy; 13881676Sjpk tname = DA_FLOPPY_NAME; 13891676Sjpk dtype = DA_FLOPPY_TYPE; 13901676Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 13911676Sjpk } else if (flag & DA_TAPE) { 13921676Sjpk dentry = dlist->tape; 13931676Sjpk tname = DA_TAPE_NAME; 13941676Sjpk dtype = DA_TAPE_TYPE; 13951676Sjpk dexec = DA_DEFAULT_TAPE_CLEAN; 13961676Sjpk } else if (flag & DA_RMDISK) { 13971676Sjpk dentry = dlist->rmdisk; 13981676Sjpk tname = DA_RMDISK_NAME; 13991676Sjpk dtype = DA_RMDISK_TYPE; 14001676Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 14011676Sjpk } else { 14021676Sjpk return (-1); 14031676Sjpk } 14041676Sjpk 14051676Sjpk for (nentry = dentry; nentry != NULL; nentry = nentry->next) { 14061676Sjpk pentry = nentry; 14071676Sjpk (void) sscanf(nentry->devinfo.devname, "%*[a-z]%d", &instance); 14081676Sjpk if (nentry->devinfo.instance == new_instance) 14091676Sjpk /* 14101676Sjpk * Add the new link name to the list of links 14111676Sjpk * that the device 'dname' has. 14121676Sjpk */ 14131676Sjpk break; 14141676Sjpk } 14151676Sjpk 14161676Sjpk if (nentry == NULL) { 14171676Sjpk /* 14181676Sjpk * Either this is the first entry ever, or no matching entry 14191676Sjpk * was found. Create a new one and add to the list. 14201676Sjpk */ 14211676Sjpk if (dentry == NULL) /* first entry ever */ 14221676Sjpk instance = 0; 14231676Sjpk else /* no matching entry */ 14241676Sjpk instance++; 14251676Sjpk (void) snprintf(dname, sizeof (dname), "%s%d", tname, instance); 14261676Sjpk if ((nentry = (deventry_t *)malloc(sizeof (deventry_t))) == 14271676Sjpk NULL) 14281676Sjpk return (-1); 14291676Sjpk if (pentry != NULL) 14301676Sjpk pentry->next = nentry; 14311676Sjpk new_entry = 1; 14321676Sjpk nentry->devinfo.devname = strdup(dname); 14331676Sjpk nentry->devinfo.devtype = dtype; 14341676Sjpk nentry->devinfo.devauths = DEFAULT_DEV_ALLOC_AUTH; 14351676Sjpk nentry->devinfo.devexec = dexec; 14361676Sjpk nentry->devinfo.instance = new_instance; 14371676Sjpk /* 14381676Sjpk * Look for default label range, authorizations and cleaning 14391676Sjpk * program in devalloc_defaults. If label range is not 14401676Sjpk * specified in devalloc_defaults, assume it to be admin_low 14411676Sjpk * to admin_high. 14421676Sjpk */ 14431676Sjpk minstr = DA_DEFAULT_MIN; 14441676Sjpk maxstr = DA_DEFAULT_MAX; 14451676Sjpk setdadefent(); 14461676Sjpk if (da_defs = getdadeftype(nentry->devinfo.devtype)) { 14471676Sjpk kva = da_defs->devopts; 14481676Sjpk if ((kval = kva_match(kva, DAOPT_MINLABEL)) != NULL) 14491676Sjpk minstr = strdup(kval); 14501676Sjpk if ((kval = kva_match(kva, DAOPT_MAXLABEL)) != NULL) 14511676Sjpk maxstr = strdup(kval); 14521676Sjpk if ((kval = kva_match(kva, DAOPT_AUTHS)) != NULL) 14531676Sjpk nentry->devinfo.devauths = strdup(kval); 14541676Sjpk if ((kval = kva_match(kva, DAOPT_CSCRIPT)) != NULL) 14551676Sjpk nentry->devinfo.devexec = strdup(kval); 14561676Sjpk freedadefent(da_defs); 14571676Sjpk } 14581676Sjpk enddadefent(); 14591676Sjpk kval = NULL; 14601676Sjpk nlen = strlen(DAOPT_MINLABEL) + strlen(KV_ASSIGN) + 14611676Sjpk strlen(minstr) + strlen(KV_TOKEN_DELIMIT) + 14621676Sjpk strlen(DAOPT_MAXLABEL) + strlen(KV_ASSIGN) + strlen(maxstr) 14631676Sjpk + 1; /* +1 for terminator */ 14641676Sjpk if (kval = (char *)malloc(nlen)) 14651676Sjpk (void) snprintf(kval, nlen, "%s%s%s%s%s%s%s", 14661676Sjpk DAOPT_MINLABEL, KV_ASSIGN, minstr, KV_TOKEN_DELIMIT, 14671676Sjpk DAOPT_MAXLABEL, KV_ASSIGN, maxstr); 14681676Sjpk nentry->devinfo.devopts = kval; 14691676Sjpk 14701676Sjpk nentry->devinfo.devlist = NULL; 14711676Sjpk nentry->next = NULL; 14721676Sjpk } 14731676Sjpk 14741676Sjpk nlen = strlen(link) + 1; /* +1 terminator */ 14751676Sjpk if (nentry->devinfo.devlist) { 14761676Sjpk plen = strlen(nentry->devinfo.devlist); 14771676Sjpk nlen = nlen + plen + 1; /* +1 for blank to separate entries */ 14781676Sjpk } else { 14791676Sjpk plen = 0; 14801676Sjpk } 14811676Sjpk 14821676Sjpk if ((nentry->devinfo.devlist = 14831676Sjpk (char *)realloc(nentry->devinfo.devlist, nlen)) == NULL) { 14841676Sjpk if (new_entry) { 14851676Sjpk nentry->devinfo.devname = NULL; 14861676Sjpk free(nentry->devinfo.devname); 14871676Sjpk nentry = NULL; 14881676Sjpk free(nentry); 14891676Sjpk if (pentry != NULL) 14901676Sjpk pentry->next = NULL; 14911676Sjpk } 14921676Sjpk return (-1); 14931676Sjpk } 14941676Sjpk 14951676Sjpk if (plen == 0) 14961676Sjpk (void) snprintf(nentry->devinfo.devlist, nlen, "%s", link); 14971676Sjpk else 14981676Sjpk (void) snprintf(nentry->devinfo.devlist + plen, nlen - plen, 14991676Sjpk " %s", link); 15001676Sjpk 15011676Sjpk if (pentry == NULL) { 15021676Sjpk /* 15031676Sjpk * This is the first entry of this device type. 15041676Sjpk */ 15051676Sjpk if (flag & DA_AUDIO) 15061676Sjpk dlist->audio = nentry; 15071676Sjpk else if (flag & DA_CD) 15081676Sjpk dlist->cd = nentry; 15091676Sjpk else if (flag & DA_FLOPPY) 15101676Sjpk dlist->floppy = nentry; 15111676Sjpk else if (flag & DA_TAPE) 15121676Sjpk dlist->tape = nentry; 15131676Sjpk else if (flag & DA_RMDISK) 15141676Sjpk dlist->rmdisk = nentry; 15151676Sjpk } 15161676Sjpk 15171676Sjpk return (0); 15181676Sjpk } 15191676Sjpk 15201676Sjpk /* 15211676Sjpk * da_remove_list - 15221676Sjpk * removes a /dev link name from the linked list of devices. 15231676Sjpk * returns type of device if link for that device removed 15241676Sjpk * successfully, else returns -1 on error. 15251676Sjpk * if all links for a device are removed, stores that device 15261676Sjpk * name in devname. 15271676Sjpk */ 15281676Sjpk int 15291676Sjpk da_remove_list(devlist_t *dlist, char *link, int type, char *devname, int size) 15301676Sjpk { 15311676Sjpk int flag; 15321676Sjpk int remove_dev = 0; 15331676Sjpk int nlen, plen, slen; 15341676Sjpk char *lasts, *lname, *oldlist; 15351676Sjpk struct stat rmstat; 15361676Sjpk deventry_t *dentry, *current, *prev; 15371676Sjpk 15381676Sjpk if (type != NULL) 15391676Sjpk flag = type; 15401676Sjpk else if (link == NULL) 15411676Sjpk return (-1); 15421676Sjpk else if (strstr(link, DA_AUDIO_NAME) || strstr(link, DA_SOUND_NAME)) 15431676Sjpk flag = DA_AUDIO; 15441676Sjpk else if (strstr(link, "dsk") || strstr(link, "rdsk") || 15451676Sjpk strstr(link, "sr") || strstr(link, "rsr")) 15461676Sjpk flag = DA_CD; 15471676Sjpk else if (strstr(link, "fd") || strstr(link, "rfd") || 15481676Sjpk strstr(link, "diskette") || strstr(link, "rdiskette")) 15491676Sjpk flag = DA_FLOPPY; 15501676Sjpk else if (strstr(link, DA_TAPE_NAME)) 15511676Sjpk flag = DA_TAPE; 15521676Sjpk else 15531676Sjpk flag = DA_RMDISK; 15541676Sjpk 15551676Sjpk switch (type) { 15561676Sjpk case DA_AUDIO: 15571676Sjpk dentry = dlist->audio; 15581676Sjpk break; 15591676Sjpk case DA_CD: 15601676Sjpk dentry = dlist->cd; 15611676Sjpk break; 15621676Sjpk case DA_FLOPPY: 15631676Sjpk dentry = dlist->floppy; 15641676Sjpk break; 15651676Sjpk case DA_TAPE: 15661676Sjpk dentry = dlist->tape; 15671676Sjpk break; 15681676Sjpk case DA_RMDISK: 15691676Sjpk dentry = dlist->rmdisk; 15701676Sjpk break; 15711676Sjpk default: 15721676Sjpk return (-1); 15731676Sjpk } 15741676Sjpk 15751676Sjpk if ((type != NULL) && (link == NULL)) { 15761676Sjpk for (current = dentry, prev = dentry; current != NULL; 15771676Sjpk current = current->next) { 15781676Sjpk oldlist = strdup(current->devinfo.devlist); 15791676Sjpk for (lname = strtok_r(oldlist, " ", &lasts); 15801676Sjpk lname != NULL; 15811676Sjpk lname = strtok_r(NULL, " ", &lasts)) { 15821676Sjpk if (stat(lname, &rmstat) != 0) { 15831676Sjpk remove_dev = 1; 15841676Sjpk goto remove_dev; 15851676Sjpk } 15861676Sjpk } 15871676Sjpk prev = current; 15881676Sjpk } 15891676Sjpk return (-1); 15901676Sjpk } 15911676Sjpk 15921676Sjpk for (current = dentry, prev = dentry; current != NULL; 15931676Sjpk current = current->next) { 15941676Sjpk plen = strlen(current->devinfo.devlist); 15951676Sjpk nlen = strlen(link); 15961676Sjpk if (plen == nlen) { 15971676Sjpk if (strcmp(current->devinfo.devlist, link) == 0) { 15981676Sjpk /* last name in the list */ 15991676Sjpk remove_dev = 1; 16001676Sjpk break; 16011676Sjpk } 16021676Sjpk } 16031676Sjpk if (strstr(current->devinfo.devlist, link)) { 16041676Sjpk nlen = plen - nlen + 1; 16051676Sjpk oldlist = strdup(current->devinfo.devlist); 16061676Sjpk if ((current->devinfo.devlist = 16071676Sjpk (char *)realloc(current->devinfo.devlist, 16081676Sjpk nlen)) == NULL) { 16091676Sjpk free(oldlist); 16101676Sjpk return (-1); 16111676Sjpk } 16121676Sjpk current->devinfo.devlist[0] = '\0'; 16131676Sjpk nlen = plen = slen = 0; 16141676Sjpk for (lname = strtok_r(oldlist, " ", &lasts); 16151676Sjpk lname != NULL; 16161676Sjpk lname = strtok_r(NULL, " ", &lasts)) { 16171676Sjpk if (strcmp(lname, link) == 0) 16181676Sjpk continue; 16191676Sjpk nlen = strlen(lname) + plen + 1; 16201676Sjpk if (plen == 0) { 16211676Sjpk slen = 16221676Sjpk snprintf(current->devinfo.devlist, 16231676Sjpk nlen, "%s", lname); 16241676Sjpk } else { 16251676Sjpk slen = 16261676Sjpk snprintf(current->devinfo.devlist + 16271676Sjpk plen, nlen - plen, " %s", 16281676Sjpk lname); 16291676Sjpk } 16301676Sjpk plen = plen + slen + 1; 16311676Sjpk } 16321676Sjpk free(oldlist); 16331676Sjpk break; 16341676Sjpk } 16351676Sjpk prev = current; 16361676Sjpk } 16371676Sjpk 16381676Sjpk remove_dev: 16391676Sjpk if (remove_dev == 1) { 16401676Sjpk (void) strlcpy(devname, current->devinfo.devname, size); 16411676Sjpk free(current->devinfo.devname); 16421676Sjpk free(current->devinfo.devlist); 16431676Sjpk current->devinfo.devname = current->devinfo.devlist = NULL; 16441676Sjpk prev->next = current->next; 16451676Sjpk free(current); 16461676Sjpk current = NULL; 16471676Sjpk } 16481676Sjpk if ((remove_dev == 1) && (prev->devinfo.devname == NULL)) { 16491676Sjpk if (prev->next) { 16501676Sjpk /* 16511676Sjpk * what we removed above was the first entry 16521676Sjpk * in the list. make the next entry to be the 16531676Sjpk * first. 16541676Sjpk */ 16551676Sjpk current = prev->next; 16561676Sjpk } else { 16571676Sjpk /* 16581676Sjpk * the matching entry was the only entry in the list 16591676Sjpk * for this type. 16601676Sjpk */ 16611676Sjpk current = NULL; 16621676Sjpk } 16631676Sjpk if (flag & DA_AUDIO) 16641676Sjpk dlist->audio = current; 16651676Sjpk else if (flag & DA_CD) 16661676Sjpk dlist->cd = current; 16671676Sjpk else if (flag & DA_FLOPPY) 16681676Sjpk dlist->floppy = current; 16691676Sjpk else if (flag & DA_TAPE) 16701676Sjpk dlist->tape = current; 16711676Sjpk else if (flag & DA_RMDISK) 16721676Sjpk dlist->rmdisk = current; 16731676Sjpk } 16741676Sjpk 16751676Sjpk return (flag); 16761676Sjpk } 16771676Sjpk 16781676Sjpk /* 16791676Sjpk * da_is_on - 16801676Sjpk * checks if device allocation feature is turned on. 16811676Sjpk * returns 1 if on, 0 if off, -1 if status string not 16821676Sjpk * found in device_allocate. 16831676Sjpk */ 16841676Sjpk int 16851676Sjpk da_is_on() 16861676Sjpk { 16871676Sjpk return (getdaon()); 16881676Sjpk } 16891676Sjpk 16901676Sjpk /* 16911676Sjpk * da_print_device - 16921676Sjpk * debug routine to print device entries. 16931676Sjpk */ 16941676Sjpk void 16951676Sjpk da_print_device(int flag, devlist_t *devlist) 16961676Sjpk { 16971676Sjpk deventry_t *entry, *dentry; 16981676Sjpk devinfo_t *devinfo; 16991676Sjpk 17001676Sjpk if (flag & DA_AUDIO) 17011676Sjpk dentry = devlist->audio; 17021676Sjpk else if (flag & DA_CD) 17031676Sjpk dentry = devlist->cd; 17041676Sjpk else if (flag & DA_FLOPPY) 17051676Sjpk dentry = devlist->floppy; 17061676Sjpk else if (flag & DA_TAPE) 17071676Sjpk dentry = devlist->tape; 17081676Sjpk else if (flag & DA_RMDISK) 17091676Sjpk dentry = devlist->rmdisk; 17101676Sjpk else 17111676Sjpk return; 17121676Sjpk 17131676Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 17141676Sjpk devinfo = &(entry->devinfo); 17151676Sjpk (void) fprintf(stdout, "name: %s\n", devinfo->devname); 17161676Sjpk (void) fprintf(stdout, "type: %s\n", devinfo->devtype); 17171676Sjpk (void) fprintf(stdout, "auth: %s\n", devinfo->devauths); 17181676Sjpk (void) fprintf(stdout, "exec: %s\n", devinfo->devexec); 17191676Sjpk (void) fprintf(stdout, "list: %s\n\n", devinfo->devlist); 17201676Sjpk } 17211676Sjpk } 1722