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*11529SJan.Parcel@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 241676Sjpk * Use is subject to license terms. 251676Sjpk */ 261676Sjpk 271676Sjpk #include <stdlib.h> 281676Sjpk #include <ctype.h> 291676Sjpk #include <unistd.h> 301676Sjpk #include <limits.h> 311676Sjpk #include <fcntl.h> 321676Sjpk #include <sys/types.h> 331676Sjpk #include <sys/stat.h> 341676Sjpk #include <utime.h> 351676Sjpk #include <synch.h> 361676Sjpk #include <strings.h> 371676Sjpk #include <string.h> 381676Sjpk #include <libintl.h> 391676Sjpk #include <errno.h> 401676Sjpk #include <auth_list.h> 41*11529SJan.Parcel@Sun.COM #include <syslog.h> 421676Sjpk #include <bsm/devices.h> 431676Sjpk #include <bsm/devalloc.h> 441676Sjpk 451676Sjpk #define DA_DEFS "/etc/security/tsol/devalloc_defaults" 461676Sjpk 471676Sjpk extern int _readbufline(char *, int, char *, int, int *); 481676Sjpk extern char *strtok_r(char *, const char *, char **); 491676Sjpk extern char *_strtok_escape(char *, char *, char **); 501676Sjpk extern int getdaon(void); 511676Sjpk extern int da_matchname(devalloc_t *, char *); 521676Sjpk extern int da_match(devalloc_t *, da_args *); 531676Sjpk extern int dmap_matchname(devmap_t *, char *); 541676Sjpk extern int dm_match(devmap_t *, da_args *); 55*11529SJan.Parcel@Sun.COM extern int dmap_matchtype(devmap_t *dmap, char *type); 56*11529SJan.Parcel@Sun.COM extern int dmap_matchdev(devmap_t *dmap, char *dev); 57*11529SJan.Parcel@Sun.COM extern int dmap_exact_dev(devmap_t *dmap, char *dev, int *num); 58*11529SJan.Parcel@Sun.COM extern char *dmap_physname(devmap_t *dmap); 591676Sjpk 601676Sjpk /* 611676Sjpk * The following structure is for recording old entries to be retained. 621676Sjpk * We read the entries from the database into a linked list in memory, 631676Sjpk * then turn around and write them out again. 641676Sjpk */ 651676Sjpk typedef struct strentry { 661676Sjpk struct strentry *se_next; 671676Sjpk char se_str[4096 + 1]; 681676Sjpk } strentry_t; 691676Sjpk 701676Sjpk /* 711676Sjpk * da_check_longindevperm - 721676Sjpk * reads /etc/logindevperm and checks if specified device is in the file. 731676Sjpk * returns 1 if specified device found in /etc/logindevperm, else returns 0 741676Sjpk */ 751676Sjpk int 761676Sjpk da_check_logindevperm(char *devname) 771676Sjpk { 781676Sjpk int ret = 0; 791676Sjpk int fd = -1; 801676Sjpk int nlen, plen, slen, lineno, fsize; 811676Sjpk char line[MAX_CANON]; 821676Sjpk char *field_delims = " \t\n"; 831676Sjpk char *fbuf = NULL; 841676Sjpk char *ptr, *device; 851676Sjpk char *lasts = NULL; 861676Sjpk FILE *fp; 871676Sjpk struct stat f_stat; 881676Sjpk 891676Sjpk /* 901676Sjpk * check if /etc/logindevperm exists and get its size 911676Sjpk */ 921676Sjpk if ((fd = open(LOGINDEVPERM, O_RDONLY)) == -1) 931676Sjpk return (0); 941676Sjpk if (fstat(fd, &f_stat) != 0) { 951676Sjpk (void) close(fd); 961676Sjpk return (0); 971676Sjpk } 981676Sjpk fsize = f_stat.st_size; 991676Sjpk if ((fbuf = (char *)malloc(fsize)) == NULL) { 1001676Sjpk (void) close(fd); 1011676Sjpk return (0); 1021676Sjpk } 1031914Scasper if ((fp = fdopen(fd, "rF")) == NULL) { 1041676Sjpk free(fbuf); 1051676Sjpk (void) close(fd); 1061676Sjpk return (0); 1071676Sjpk } 1081676Sjpk 1091676Sjpk /* 1101676Sjpk * read and parse /etc/logindevperm 1111676Sjpk */ 1121676Sjpk plen = nlen = lineno = 0; 1131676Sjpk while (fgets(line, MAX_CANON, fp) != NULL) { 1141676Sjpk lineno++; 1151676Sjpk if ((ptr = strchr(line, '#')) != NULL) 1161676Sjpk *ptr = '\0'; /* handle comments */ 1171676Sjpk if (strtok_r(line, field_delims, &lasts) == NULL) 1181676Sjpk continue; /* ignore blank lines */ 1191676Sjpk if (strtok_r(NULL, field_delims, &lasts) == NULL) 1201676Sjpk /* invalid entry */ 1211676Sjpk continue; 1221676Sjpk if ((ptr = strtok_r(NULL, field_delims, &lasts)) == NULL) 1231676Sjpk /* empty device list */ 1241676Sjpk continue; 1251676Sjpk nlen = strlen(ptr) + 1; /* +1 terminator */ 1261676Sjpk nlen += (plen + 1); 1271676Sjpk if (plen == 0) 1281676Sjpk slen = snprintf(fbuf, nlen, "%s", ptr); 1291676Sjpk else 1301676Sjpk slen = snprintf(fbuf + plen, nlen - plen, ":%s", ptr); 1311676Sjpk if (slen >= fsize) { 1321676Sjpk fbuf[0] = '\0'; 1331676Sjpk (void) fclose(fp); 1341676Sjpk return (slen); 1351676Sjpk } 1361676Sjpk plen += slen; 1371676Sjpk } 1381676Sjpk (void) fclose(fp); 1391676Sjpk 1401676Sjpk /* 1411676Sjpk * check if devname exists in /etc/logindevperm 1421676Sjpk */ 1431676Sjpk device = strtok_r(fbuf, ":", &lasts); 1441676Sjpk while (device != NULL) { 1451676Sjpk /* 1461676Sjpk * device and devname may be one of these types - 1471676Sjpk * /dev/xx 1481676Sjpk * /dev/xx* 1491676Sjpk * /dev/dir/xx 1501676Sjpk * /dev/dir/xx* 1511676Sjpk * /dev/dir/"*" 1521676Sjpk */ 1531676Sjpk if (strcmp(device, devname) == 0) { 1541676Sjpk /* /dev/xx, /dev/dir/xx */ 1551676Sjpk free(fbuf); 1561676Sjpk return (1); 1571676Sjpk } 1581676Sjpk if ((ptr = strrchr(device, KV_WILDCHAR)) != NULL) { 1591676Sjpk /* all wildcard types */ 1601676Sjpk *ptr = '\0'; 1611676Sjpk if (strncmp(device, devname, strlen(device)) == 0) { 1621676Sjpk free(fbuf); 1631676Sjpk return (1); 1641676Sjpk } 1651676Sjpk } 1661676Sjpk device = strtok_r(NULL, ":", &lasts); 1671676Sjpk } 1681676Sjpk 1691676Sjpk return (ret); 1701676Sjpk } 1711676Sjpk 1721676Sjpk /* 1731676Sjpk * _da_read_file - 1741676Sjpk * establishes readers/writer lock on fname; reads in the file if its 1751676Sjpk * contents changed since the last time we read it. 1761676Sjpk * returns size of buffer read, or -1 on failure. 1771676Sjpk */ 1781676Sjpk int 1791676Sjpk _da_read_file(char *fname, char **fbuf, time_t *ftime, rwlock_t *flock, 1801676Sjpk int flag) 1811676Sjpk { 1821676Sjpk int fd = -1; 1831676Sjpk int fsize = 0; 1841676Sjpk time_t newtime; 1851676Sjpk struct stat f_stat; 1861676Sjpk 1871676Sjpk if (flag & DA_FORCE) 1881676Sjpk *ftime = 0; 1891676Sjpk 1901676Sjpk /* check the size and the time stamp on the file */ 1911676Sjpk if (rw_rdlock(flock) != 0) 1921676Sjpk return (-1); 1931676Sjpk if (stat(fname, &f_stat) != 0) { 1941676Sjpk (void) rw_unlock(flock); 1951676Sjpk return (-1); 1961676Sjpk } 1971676Sjpk fsize = f_stat.st_size; 1981676Sjpk newtime = f_stat.st_mtime; 1991676Sjpk (void) rw_unlock(flock); 2001676Sjpk 2011676Sjpk while (newtime > *ftime) { 2021676Sjpk /* 2031676Sjpk * file has been modified since we last read it; or this 2041676Sjpk * is a forced read. 2051676Sjpk * read file into the buffer with rw lock. 2061676Sjpk */ 2071676Sjpk if (rw_wrlock(flock) != 0) 2081676Sjpk return (-1); 2091914Scasper if ((fd = open(fname, O_RDONLY)) == -1) { 2101676Sjpk (void) rw_unlock(flock); 2111676Sjpk return (-1); 2121676Sjpk } 2131676Sjpk if (*fbuf != NULL) { 2141676Sjpk free(*fbuf); 2151676Sjpk *fbuf = NULL; 2161676Sjpk } 2171676Sjpk if ((*fbuf = malloc(fsize)) == NULL) { 2181676Sjpk (void) rw_unlock(flock); 2191676Sjpk (void) close(fd); 2201676Sjpk return (-1); 2211676Sjpk } 2221676Sjpk if (read(fd, *fbuf, fsize) < fsize) { 2231676Sjpk free(*fbuf); 2241676Sjpk (void) rw_unlock(flock); 2251676Sjpk (void) close(fd); 2261676Sjpk return (-1); 2271676Sjpk } 2281676Sjpk (void) rw_unlock(flock); 2291676Sjpk /* 2301676Sjpk * verify that the file did not change just after we read it. 2311676Sjpk */ 2321676Sjpk if (rw_rdlock(flock) != 0) { 2331676Sjpk free(*fbuf); 2341676Sjpk (void) close(fd); 2351676Sjpk return (-1); 2361676Sjpk } 2371676Sjpk if (stat(fname, &f_stat) != 0) { 2381676Sjpk free(*fbuf); 2391676Sjpk (void) rw_unlock(flock); 2401676Sjpk (void) close(fd); 2411676Sjpk return (-1); 2421676Sjpk } 2431676Sjpk fsize = f_stat.st_size; 2441676Sjpk newtime = f_stat.st_mtime; 2451676Sjpk (void) rw_unlock(flock); 2461676Sjpk (void) close(fd); 2471676Sjpk *ftime = newtime; 2481676Sjpk } 2491676Sjpk 2501676Sjpk return (fsize); 2511676Sjpk } 2521676Sjpk 2531676Sjpk /* 2541676Sjpk * _update_zonename - 2551676Sjpk * add/remove current zone's name to the given devalloc_t. 2561676Sjpk */ 2571676Sjpk void 2581676Sjpk _update_zonename(da_args *dargs, devalloc_t *dap) 2591676Sjpk { 2601676Sjpk int i, j; 2611676Sjpk int oldsize, newsize; 2621676Sjpk int has_zonename = 0; 2631676Sjpk char *zonename; 2641676Sjpk kva_t *newkva, *oldkva; 2651676Sjpk kv_t *newdata, *olddata; 2661676Sjpk devinfo_t *devinfo; 2671676Sjpk 2681676Sjpk devinfo = dargs->devinfo; 2691676Sjpk oldkva = dap->da_devopts; 2701676Sjpk if (oldkva == NULL) { 2711676Sjpk if (dargs->optflag & DA_REMOVE_ZONE) 2721676Sjpk return; 2731676Sjpk if (dargs->optflag & DA_ADD_ZONE) { 2741676Sjpk newkva = _str2kva(devinfo->devopts, KV_ASSIGN, 2751676Sjpk KV_TOKEN_DELIMIT); 2761676Sjpk if (newkva != NULL) 2771676Sjpk dap->da_devopts = newkva; 2781676Sjpk return; 2791676Sjpk } 2801676Sjpk } 2811676Sjpk newsize = oldsize = oldkva->length; 2821676Sjpk if (kva_match(oldkva, DAOPT_ZONE)) 2831676Sjpk has_zonename = 1; 2841676Sjpk if (dargs->optflag & DA_ADD_ZONE) { 2851676Sjpk if ((zonename = index(devinfo->devopts, '=')) == NULL) 2861676Sjpk return; 2871676Sjpk zonename++; 2881676Sjpk if (has_zonename) { 2891676Sjpk (void) _insert2kva(oldkva, DAOPT_ZONE, zonename); 2901676Sjpk return; 2911676Sjpk } 2921676Sjpk newsize += 1; 2931676Sjpk } else if (dargs->optflag & DA_REMOVE_ZONE) { 2941676Sjpk if (has_zonename) { 2951676Sjpk newsize -= 1; 2961676Sjpk if (newsize == 0) { 2971676Sjpk /* 2981676Sjpk * If zone name was the only key/value pair, 2991676Sjpk * put 'reserved' in the empty slot. 3001676Sjpk */ 3011676Sjpk _kva_free(oldkva); 3021676Sjpk dap->da_devopts = NULL; 3031676Sjpk return; 3041676Sjpk } 3051676Sjpk } else { 3061676Sjpk return; 3071676Sjpk } 3081676Sjpk } 3091676Sjpk newkva = _new_kva(newsize); 3101676Sjpk newkva->length = 0; 3111676Sjpk newdata = newkva->data; 3121676Sjpk olddata = oldkva->data; 3131676Sjpk for (i = 0, j = 0; i < oldsize; i++) { 3141676Sjpk if ((dargs->optflag & DA_REMOVE_ZONE) && 3151676Sjpk (strcmp(olddata[i].key, DAOPT_ZONE) == 0)) 3161676Sjpk continue; 3171676Sjpk newdata[j].key = strdup(olddata[i].key); 3181676Sjpk newdata[j].value = strdup(olddata[i].value); 3191676Sjpk newkva->length++; 3201676Sjpk j++; 3211676Sjpk } 3221676Sjpk if (dargs->optflag & DA_ADD_ZONE) { 3231676Sjpk newdata[j].key = strdup(DAOPT_ZONE); 3241676Sjpk newdata[j].value = strdup(zonename); 3251676Sjpk newkva->length++; 3261676Sjpk } 3271676Sjpk _kva_free(oldkva); 3281676Sjpk dap->da_devopts = newkva; 3291676Sjpk } 3301676Sjpk 3311676Sjpk /* 3321676Sjpk * _dmap2str - 3331676Sjpk * converts a device_map entry into a printable string 3341676Sjpk * returns 0 on success, -1 on error. 3351676Sjpk */ 3361676Sjpk /*ARGSUSED*/ 3371676Sjpk static int 338*11529SJan.Parcel@Sun.COM _dmap2str(devmap_t *dmp, char *buf, int size, const char *sep) 3391676Sjpk { 3401676Sjpk int length; 3411676Sjpk 3421676Sjpk length = snprintf(buf, size, "%s%s", dmp->dmap_devname, sep); 3431676Sjpk if (length >= size) 3441676Sjpk return (-1); 3451676Sjpk length += snprintf(buf + length, size - length, "%s%s", 3461676Sjpk dmp->dmap_devtype, sep); 3471676Sjpk if (length >= size) 3481676Sjpk return (-1); 3491676Sjpk length += snprintf(buf + length, size - length, "%s\n", 3501676Sjpk dmp->dmap_devlist); 3511676Sjpk if (length >= size) 3521676Sjpk return (-1); 3531676Sjpk return (0); 3541676Sjpk } 3551676Sjpk 3561676Sjpk /* 3571676Sjpk * _dmap2strentry - 3581676Sjpk * calls dmap2str to break given devmap_t into printable entry. 3591676Sjpk * returns pointer to decoded entry, NULL on error. 3601676Sjpk */ 3611676Sjpk static strentry_t * 362*11529SJan.Parcel@Sun.COM _dmap2strentry(devmap_t *devmapp) 3631676Sjpk { 3641676Sjpk strentry_t *sep; 3651676Sjpk 3661676Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 3671676Sjpk return (NULL); 368*11529SJan.Parcel@Sun.COM if (_dmap2str(devmapp, sep->se_str, sizeof (sep->se_str), 3691676Sjpk KV_TOKEN_DELIMIT"\\\n\t") != 0) { 3701676Sjpk free(sep); 3711676Sjpk return (NULL); 3721676Sjpk } 3731676Sjpk return (sep); 3741676Sjpk } 3751676Sjpk 3761676Sjpk /* 3771676Sjpk * fix_optstr - 3781676Sjpk * removes trailing ':' from buf. 3791676Sjpk */ 3801676Sjpk void 3811676Sjpk fix_optstr(char *buf) 3821676Sjpk { 3831676Sjpk char *p = NULL; 3841676Sjpk 3851676Sjpk if (p = rindex(buf, ':')) 3861676Sjpk *p = ';'; 3871676Sjpk } 3881676Sjpk 3891676Sjpk /* 3901676Sjpk * _da2str - 3911676Sjpk * converts a device_allocate entry into a printable string 3921676Sjpk * returns 0 on success, -1 on error. 3931676Sjpk */ 3941676Sjpk static int 3951676Sjpk _da2str(da_args *dargs, devalloc_t *dap, char *buf, int size, const char *sep, 3961676Sjpk const char *osep) 3971676Sjpk { 3981676Sjpk int length; 3991676Sjpk int matching_entry = 0; 4001676Sjpk char **dnames; 4011676Sjpk 4021676Sjpk if (dargs->optflag & DA_UPDATE && 4031676Sjpk (dargs->optflag & DA_ADD_ZONE || 4041676Sjpk dargs->optflag & DA_REMOVE_ZONE) && 4051676Sjpk dargs->devnames) { 4061676Sjpk for (dnames = dargs->devnames; *dnames != NULL; dnames++) { 4071676Sjpk if (da_matchname(dap, *dnames)) { 4081676Sjpk matching_entry = 1; 4091676Sjpk break; 4101676Sjpk } 4111676Sjpk } 4121676Sjpk } 4131676Sjpk length = snprintf(buf, size, "%s%s", dap->da_devname, sep); 4141676Sjpk if (length >= size) 4151676Sjpk return (-1); 4161676Sjpk length += snprintf(buf + length, size - length, "%s%s", 4171676Sjpk dap->da_devtype, sep); 4181676Sjpk if (length >= size) 4191676Sjpk return (-1); 4201676Sjpk if (matching_entry) 4211676Sjpk _update_zonename(dargs, dap); 4221676Sjpk if ((dap->da_devopts == NULL) || ((dap->da_devopts->length == 1) && 4231676Sjpk (strcmp(dap->da_devopts->data->key, DA_RESERVED) == 0))) { 4241676Sjpk length += snprintf(buf + length, size - length, "%s%s", 4251676Sjpk DA_RESERVED, sep); 4261676Sjpk } else { 4271676Sjpk if (_kva2str(dap->da_devopts, buf + length, size - length, 4281676Sjpk KV_ASSIGN, (char *)osep) != 0) 4291676Sjpk return (-1); 4301676Sjpk length = strlen(buf); 4311676Sjpk } 4321676Sjpk if (dap->da_devopts) 4331676Sjpk fix_optstr(buf); 4341676Sjpk if (length >= size) 4351676Sjpk return (-1); 4361676Sjpk length += snprintf(buf + length, size - length, "%s%s", 4371676Sjpk DA_RESERVED, sep); 4381676Sjpk if (length >= size) 4391676Sjpk return (-1); 4401676Sjpk length += snprintf(buf + length, size - length, "%s%s", 4411676Sjpk dap->da_devauth ? dap->da_devauth : DA_ANYUSER, sep); 4421676Sjpk if (length >= size) 4431676Sjpk return (-1); 4441676Sjpk length += snprintf(buf + length, size - length, "%s\n", 4451676Sjpk dap->da_devexec ? dap->da_devexec : ""); 4461676Sjpk if (length >= size) 4471676Sjpk return (-1); 4481676Sjpk 4491676Sjpk return (0); 4501676Sjpk } 4511676Sjpk 4521676Sjpk /* 4531676Sjpk * _da2strentry - 4541676Sjpk * calls da2str to break given devalloc_t into printable entry. 4551676Sjpk * returns pointer to decoded entry, NULL on error. 4561676Sjpk */ 4571676Sjpk static strentry_t * 4581676Sjpk _da2strentry(da_args *dargs, devalloc_t *dap) 4591676Sjpk { 4601676Sjpk strentry_t *sep; 4611676Sjpk 4621676Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 4631676Sjpk return (NULL); 4641676Sjpk if (_da2str(dargs, dap, sep->se_str, sizeof (sep->se_str), 4651676Sjpk KV_DELIMITER "\\\n\t", KV_TOKEN_DELIMIT "\\\n\t") != 0) { 4661676Sjpk free(sep); 4671676Sjpk return (NULL); 4681676Sjpk } 4691676Sjpk return (sep); 4701676Sjpk } 4711676Sjpk 4721676Sjpk /* 4731676Sjpk * _def2str 4741676Sjpk * converts da_defs_t into a printable string. 4751676Sjpk * returns 0 on success, -1 on error. 4761676Sjpk */ 4771676Sjpk static int 4781676Sjpk _def2str(da_defs_t *da_defs, char *buf, int size, const char *sep) 4791676Sjpk { 4801676Sjpk int length; 4811676Sjpk 4821676Sjpk length = snprintf(buf, size, "%s%s", da_defs->devtype, sep); 4831676Sjpk if (length >= size) 4841676Sjpk return (-1); 4851676Sjpk if (da_defs->devopts) { 4861676Sjpk if (_kva2str(da_defs->devopts, buf + length, size - length, 4871676Sjpk KV_ASSIGN, KV_DELIMITER) != 0) 4881676Sjpk return (-1); 4891676Sjpk length = strlen(buf); 4901676Sjpk } 4911676Sjpk if (length >= size) 4921676Sjpk return (-1); 4931676Sjpk 4941676Sjpk return (0); 4951676Sjpk } 4961676Sjpk 4971676Sjpk /* 4981676Sjpk * _def2strentry 4991676Sjpk * calls _def2str to break given da_defs_t into printable entry. 5001676Sjpk * returns pointer decoded entry, NULL on error. 5011676Sjpk */ 5021676Sjpk static strentry_t * 5031676Sjpk _def2strentry(da_defs_t *da_defs) 5041676Sjpk { 5051676Sjpk strentry_t *sep; 5061676Sjpk 5071676Sjpk if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL) 5081676Sjpk return (NULL); 5091676Sjpk if (_def2str(da_defs, sep->se_str, sizeof (sep->se_str), 5101676Sjpk KV_TOKEN_DELIMIT) != 0) { 5111676Sjpk free(sep); 5121676Sjpk return (NULL); 5131676Sjpk } 5141676Sjpk 5151676Sjpk return (sep); 5161676Sjpk } 5171676Sjpk 5181676Sjpk /* 5191676Sjpk * _build_defattrs 5201676Sjpk * cycles through all defattr entries, stores them in memory. removes 5211676Sjpk * entries with the given search_key (device type). 5221676Sjpk * returns 0 if given entry not found, 1 if given entry removed, 2 on 5231676Sjpk * error. 5241676Sjpk */ 5251676Sjpk static int 5261676Sjpk _build_defattrs(da_args *dargs, strentry_t **head_defent) 5271676Sjpk { 5281676Sjpk int rc = 0; 5291676Sjpk da_defs_t *da_defs; 5301676Sjpk strentry_t *tail_str, *tmp_str; 5311676Sjpk 5321676Sjpk setdadefent(); 5331676Sjpk while ((da_defs = getdadefent()) != NULL) { 5341676Sjpk rc = !(strcmp(da_defs->devtype, dargs->devinfo->devtype)); 5351676Sjpk if (rc && dargs->optflag & DA_ADD && 5361676Sjpk !(dargs->optflag & DA_FORCE)) { 5371676Sjpk /* 5381676Sjpk * During DA_ADD, we keep an existing entry unless 5391676Sjpk * we have DA_FORCE set to override that entry. 5401676Sjpk */ 5411676Sjpk dargs->optflag |= DA_NO_OVERRIDE; 5421676Sjpk rc = 0; 5431676Sjpk } 5441676Sjpk if (rc == 0) { 5451676Sjpk tmp_str = _def2strentry(da_defs); 5461676Sjpk if (tmp_str == NULL) { 5471676Sjpk freedadefent(da_defs); 5481676Sjpk enddadefent(); 5491676Sjpk return (2); 5501676Sjpk } 5511676Sjpk /* retaining defattr entry: tmp_str->se_str */ 5521676Sjpk tmp_str->se_next = NULL; 5531676Sjpk if (*head_defent == NULL) { 5541676Sjpk *head_defent = tail_str = tmp_str; 5551676Sjpk } else { 5561676Sjpk tail_str->se_next = tmp_str; 5571676Sjpk tail_str = tmp_str; 5581676Sjpk } 5591676Sjpk } 5601676Sjpk freedadefent(da_defs); 5611676Sjpk } 5621676Sjpk enddadefent(); 5631676Sjpk 5641676Sjpk return (rc); 5651676Sjpk } 5661676Sjpk 5671676Sjpk /* 568*11529SJan.Parcel@Sun.COM * _rebuild_lists - 569*11529SJan.Parcel@Sun.COM * 570*11529SJan.Parcel@Sun.COM * If dargs->optflag & DA_EVENT, does not assume the dargs list is 571*11529SJan.Parcel@Sun.COM * complete or completely believable, since devfsadm caches 572*11529SJan.Parcel@Sun.COM * ONLY what it has been exposed to via syseventd. 573*11529SJan.Parcel@Sun.COM * 574*11529SJan.Parcel@Sun.COM * Cycles through all the entries in the /etc files, stores them 575*11529SJan.Parcel@Sun.COM * in memory, takes note of device->dname numbers (i.e. rmdisk0, 576*11529SJan.Parcel@Sun.COM * rmdisk12) 577*11529SJan.Parcel@Sun.COM * 578*11529SJan.Parcel@Sun.COM * Cycles through again, adds dargs entry 579*11529SJan.Parcel@Sun.COM * with the name tname%d (lowest unused number for the device type) 580*11529SJan.Parcel@Sun.COM * to the list of things for the caller to write out to a file, 581*11529SJan.Parcel@Sun.COM * IFF it is a new entry. 582*11529SJan.Parcel@Sun.COM * 583*11529SJan.Parcel@Sun.COM * It is an error for it to already be there. 584*11529SJan.Parcel@Sun.COM * 585*11529SJan.Parcel@Sun.COM * Add: 586*11529SJan.Parcel@Sun.COM * Returns 0 if successful and 2 on error. 587*11529SJan.Parcel@Sun.COM * Remove: 588*11529SJan.Parcel@Sun.COM * Returns 0 if not found, 1 if found, 2 on error. 589*11529SJan.Parcel@Sun.COM */ 590*11529SJan.Parcel@Sun.COM static int 591*11529SJan.Parcel@Sun.COM _rebuild_lists(da_args *dargs, strentry_t **head_devallocp, 592*11529SJan.Parcel@Sun.COM strentry_t **head_devmapp) 593*11529SJan.Parcel@Sun.COM { 594*11529SJan.Parcel@Sun.COM int rc = 0; 595*11529SJan.Parcel@Sun.COM devalloc_t *devallocp; 596*11529SJan.Parcel@Sun.COM devmap_t *devmapp; 597*11529SJan.Parcel@Sun.COM strentry_t *tail_str; 598*11529SJan.Parcel@Sun.COM strentry_t *tmp_str; 599*11529SJan.Parcel@Sun.COM uint64_t tmp_bitmap = 0; 600*11529SJan.Parcel@Sun.COM int tmp = 0; 601*11529SJan.Parcel@Sun.COM char new_devname[DA_MAXNAME + 1]; 602*11529SJan.Parcel@Sun.COM char errmsg[DA_MAXNAME + 1 + (PATH_MAX * 2) + 80]; 603*11529SJan.Parcel@Sun.COM char *realname; 604*11529SJan.Parcel@Sun.COM int suffix = DA_MAX_DEVNO + 1; 605*11529SJan.Parcel@Sun.COM int found = 0; 606*11529SJan.Parcel@Sun.COM 607*11529SJan.Parcel@Sun.COM if (dargs->optflag & (DA_MAPS_ONLY | DA_ALLOC_ONLY)) 608*11529SJan.Parcel@Sun.COM return (2); 609*11529SJan.Parcel@Sun.COM 610*11529SJan.Parcel@Sun.COM if (dargs->optflag & DA_FORCE) 611*11529SJan.Parcel@Sun.COM return (2); 612*11529SJan.Parcel@Sun.COM 613*11529SJan.Parcel@Sun.COM /* read both files, maps first so we can compare actual devices */ 614*11529SJan.Parcel@Sun.COM 615*11529SJan.Parcel@Sun.COM /* build device_maps */ 616*11529SJan.Parcel@Sun.COM setdmapent(); 617*11529SJan.Parcel@Sun.COM while ((devmapp = getdmapent()) != NULL) { 618*11529SJan.Parcel@Sun.COM if ((rc = dmap_matchtype(devmapp, dargs->devinfo->devtype)) 619*11529SJan.Parcel@Sun.COM == 1) { 620*11529SJan.Parcel@Sun.COM if (dargs->optflag & DA_REMOVE) { 621*11529SJan.Parcel@Sun.COM if ((devmapp->dmap_devarray == NULL) || 622*11529SJan.Parcel@Sun.COM (devmapp->dmap_devarray[0] == NULL)) { 623*11529SJan.Parcel@Sun.COM freedmapent(devmapp); 624*11529SJan.Parcel@Sun.COM enddmapent(); 625*11529SJan.Parcel@Sun.COM return (2); 626*11529SJan.Parcel@Sun.COM } 627*11529SJan.Parcel@Sun.COM realname = dmap_physname(devmapp); 628*11529SJan.Parcel@Sun.COM if (realname == NULL) { 629*11529SJan.Parcel@Sun.COM freedmapent(devmapp); 630*11529SJan.Parcel@Sun.COM enddmapent(); 631*11529SJan.Parcel@Sun.COM return (2); 632*11529SJan.Parcel@Sun.COM } 633*11529SJan.Parcel@Sun.COM if (strstr(realname, dargs->devinfo->devlist) 634*11529SJan.Parcel@Sun.COM != NULL) { 635*11529SJan.Parcel@Sun.COM if (dargs->devinfo->devname != NULL) 636*11529SJan.Parcel@Sun.COM free(dargs->devinfo->devname); 637*11529SJan.Parcel@Sun.COM dargs->devinfo->devname = 638*11529SJan.Parcel@Sun.COM strdup(devmapp->dmap_devname); 639*11529SJan.Parcel@Sun.COM found = 1; 640*11529SJan.Parcel@Sun.COM freedmapent(devmapp); 641*11529SJan.Parcel@Sun.COM continue; /* don't retain */ 642*11529SJan.Parcel@Sun.COM } 643*11529SJan.Parcel@Sun.COM } else if (dargs->optflag & DA_ADD) { 644*11529SJan.Parcel@Sun.COM /* 645*11529SJan.Parcel@Sun.COM * Need to know which suffixes are in use 646*11529SJan.Parcel@Sun.COM */ 647*11529SJan.Parcel@Sun.COM rc = (dmap_exact_dev(devmapp, 648*11529SJan.Parcel@Sun.COM dargs->devinfo->devlist, &suffix)); 649*11529SJan.Parcel@Sun.COM 650*11529SJan.Parcel@Sun.COM if (rc == 0) { 651*11529SJan.Parcel@Sun.COM /* 652*11529SJan.Parcel@Sun.COM * Same type, different device. Record 653*11529SJan.Parcel@Sun.COM * device suffix already in use. 654*11529SJan.Parcel@Sun.COM */ 655*11529SJan.Parcel@Sun.COM if (suffix > DA_MAX_DEVNO) { 656*11529SJan.Parcel@Sun.COM freedmapent(devmapp); 657*11529SJan.Parcel@Sun.COM enddmapent(); 658*11529SJan.Parcel@Sun.COM return (2); 659*11529SJan.Parcel@Sun.COM } 660*11529SJan.Parcel@Sun.COM tmp_bitmap |= (uint64_t)(1LL << suffix); 661*11529SJan.Parcel@Sun.COM } else { 662*11529SJan.Parcel@Sun.COM /* 663*11529SJan.Parcel@Sun.COM * Match on add is an error 664*11529SJan.Parcel@Sun.COM * or mapping attempt returned error 665*11529SJan.Parcel@Sun.COM */ 666*11529SJan.Parcel@Sun.COM freedmapent(devmapp); 667*11529SJan.Parcel@Sun.COM enddmapent(); 668*11529SJan.Parcel@Sun.COM return (2); 669*11529SJan.Parcel@Sun.COM } 670*11529SJan.Parcel@Sun.COM } else 671*11529SJan.Parcel@Sun.COM /* add other transaction types as needed */ 672*11529SJan.Parcel@Sun.COM return (2); 673*11529SJan.Parcel@Sun.COM 674*11529SJan.Parcel@Sun.COM } /* if same type */ 675*11529SJan.Parcel@Sun.COM 676*11529SJan.Parcel@Sun.COM tmp_str = _dmap2strentry(devmapp); 677*11529SJan.Parcel@Sun.COM if (tmp_str == NULL) { 678*11529SJan.Parcel@Sun.COM freedmapent(devmapp); 679*11529SJan.Parcel@Sun.COM enddmapent(); 680*11529SJan.Parcel@Sun.COM return (2); 681*11529SJan.Parcel@Sun.COM } 682*11529SJan.Parcel@Sun.COM /* retaining devmap entry: tmp_str->se_str */ 683*11529SJan.Parcel@Sun.COM tmp_str->se_next = NULL; 684*11529SJan.Parcel@Sun.COM if (*head_devmapp == NULL) { 685*11529SJan.Parcel@Sun.COM *head_devmapp = tail_str = tmp_str; 686*11529SJan.Parcel@Sun.COM } else { 687*11529SJan.Parcel@Sun.COM tail_str->se_next = tmp_str; 688*11529SJan.Parcel@Sun.COM tail_str = tmp_str; 689*11529SJan.Parcel@Sun.COM } 690*11529SJan.Parcel@Sun.COM freedmapent(devmapp); 691*11529SJan.Parcel@Sun.COM } 692*11529SJan.Parcel@Sun.COM enddmapent(); 693*11529SJan.Parcel@Sun.COM 694*11529SJan.Parcel@Sun.COM /* 695*11529SJan.Parcel@Sun.COM * No need to rewrite the files if the item to be removed is not 696*11529SJan.Parcel@Sun.COM * in the files -- wait for another call on another darg. 697*11529SJan.Parcel@Sun.COM */ 698*11529SJan.Parcel@Sun.COM if ((dargs->optflag & DA_REMOVE) && !found) 699*11529SJan.Parcel@Sun.COM return (0); 700*11529SJan.Parcel@Sun.COM 701*11529SJan.Parcel@Sun.COM 702*11529SJan.Parcel@Sun.COM if (dargs->optflag & DA_ADD) { 703*11529SJan.Parcel@Sun.COM /* 704*11529SJan.Parcel@Sun.COM * Since we got here from an event, we know the stored 705*11529SJan.Parcel@Sun.COM * devname is a useless guess, since the files had not 706*11529SJan.Parcel@Sun.COM * been read when the name was chosen, and we don't keep 707*11529SJan.Parcel@Sun.COM * them anywhere else that is sufficiently definitive. 708*11529SJan.Parcel@Sun.COM */ 709*11529SJan.Parcel@Sun.COM 710*11529SJan.Parcel@Sun.COM for (tmp = 0; tmp <= DA_MAX_DEVNO; tmp++) 711*11529SJan.Parcel@Sun.COM if (!(tmp_bitmap & (1LL << tmp))) 712*11529SJan.Parcel@Sun.COM break; 713*11529SJan.Parcel@Sun.COM /* Future: support more than 64 hotplug devices per type? */ 714*11529SJan.Parcel@Sun.COM if (tmp > DA_MAX_DEVNO) 715*11529SJan.Parcel@Sun.COM return (2); 716*11529SJan.Parcel@Sun.COM 717*11529SJan.Parcel@Sun.COM (void) snprintf(new_devname, DA_MAXNAME + 1, "%s%u", 718*11529SJan.Parcel@Sun.COM dargs->devinfo->devtype, tmp); 719*11529SJan.Parcel@Sun.COM if (dargs->devinfo->devname != NULL) 720*11529SJan.Parcel@Sun.COM free(dargs->devinfo->devname); 721*11529SJan.Parcel@Sun.COM dargs->devinfo->devname = strdup(new_devname); 722*11529SJan.Parcel@Sun.COM } 723*11529SJan.Parcel@Sun.COM 724*11529SJan.Parcel@Sun.COM /* 725*11529SJan.Parcel@Sun.COM * Now adjust devalloc list to match devmaps 726*11529SJan.Parcel@Sun.COM * Note we now have the correct devname for da_match to use. 727*11529SJan.Parcel@Sun.COM */ 728*11529SJan.Parcel@Sun.COM setdaent(); 729*11529SJan.Parcel@Sun.COM while ((devallocp = getdaent()) != NULL) { 730*11529SJan.Parcel@Sun.COM rc = da_match(devallocp, dargs); 731*11529SJan.Parcel@Sun.COM if (rc == 1) { 732*11529SJan.Parcel@Sun.COM if (dargs->optflag & DA_ADD) { 733*11529SJan.Parcel@Sun.COM /* logging is on if DA_EVENT is set */ 734*11529SJan.Parcel@Sun.COM if (dargs->optflag & DA_EVENT) { 735*11529SJan.Parcel@Sun.COM (void) snprintf(errmsg, sizeof (errmsg), 736*11529SJan.Parcel@Sun.COM "%s and %s out of sync," 737*11529SJan.Parcel@Sun.COM "%s only in %s.", 738*11529SJan.Parcel@Sun.COM DEVALLOC, DEVMAP, 739*11529SJan.Parcel@Sun.COM devallocp->da_devname, DEVALLOC); 740*11529SJan.Parcel@Sun.COM syslog(LOG_ERR, "%s", errmsg); 741*11529SJan.Parcel@Sun.COM } 742*11529SJan.Parcel@Sun.COM freedaent(devallocp); 743*11529SJan.Parcel@Sun.COM enddaent(); 744*11529SJan.Parcel@Sun.COM return (2); 745*11529SJan.Parcel@Sun.COM } else if (dargs->optflag & DA_REMOVE) { 746*11529SJan.Parcel@Sun.COM /* make list w/o this entry */ 747*11529SJan.Parcel@Sun.COM freedaent(devallocp); 748*11529SJan.Parcel@Sun.COM continue; 749*11529SJan.Parcel@Sun.COM } 750*11529SJan.Parcel@Sun.COM } 751*11529SJan.Parcel@Sun.COM tmp_str = _da2strentry(dargs, devallocp); 752*11529SJan.Parcel@Sun.COM if (tmp_str == NULL) { 753*11529SJan.Parcel@Sun.COM freedaent(devallocp); 754*11529SJan.Parcel@Sun.COM enddaent(); 755*11529SJan.Parcel@Sun.COM return (2); 756*11529SJan.Parcel@Sun.COM } 757*11529SJan.Parcel@Sun.COM /* retaining devalloc entry: tmp_str->se_str */ 758*11529SJan.Parcel@Sun.COM tmp_str->se_next = NULL; 759*11529SJan.Parcel@Sun.COM if (*head_devallocp == NULL) { 760*11529SJan.Parcel@Sun.COM *head_devallocp = tail_str = tmp_str; 761*11529SJan.Parcel@Sun.COM } else { 762*11529SJan.Parcel@Sun.COM tail_str->se_next = tmp_str; 763*11529SJan.Parcel@Sun.COM tail_str = tmp_str; 764*11529SJan.Parcel@Sun.COM } 765*11529SJan.Parcel@Sun.COM freedaent(devallocp); 766*11529SJan.Parcel@Sun.COM } 767*11529SJan.Parcel@Sun.COM enddaent(); 768*11529SJan.Parcel@Sun.COM 769*11529SJan.Parcel@Sun.COM /* the caller needs to know if a remove needs to rewrite files */ 770*11529SJan.Parcel@Sun.COM if (dargs->optflag & DA_REMOVE) 771*11529SJan.Parcel@Sun.COM return (1); /* 0 and 2 cases returned earlier */ 772*11529SJan.Parcel@Sun.COM 773*11529SJan.Parcel@Sun.COM return (0); /* Successful DA_ADD */ 774*11529SJan.Parcel@Sun.COM } 775*11529SJan.Parcel@Sun.COM /* 7761676Sjpk * _build_lists - 777*11529SJan.Parcel@Sun.COM * Cycles through all the entries, stores them in memory. removes entries 7781676Sjpk * with the given search_key (device name or type). 7791676Sjpk * returns 0 if given entry not found, 1 if given entry removed, 2 on 7801676Sjpk * error. 7811676Sjpk */ 7821676Sjpk static int 7831676Sjpk _build_lists(da_args *dargs, strentry_t **head_devallocp, 7841676Sjpk strentry_t **head_devmapp) 7851676Sjpk { 7861676Sjpk int rc = 0; 7871676Sjpk devalloc_t *devallocp; 7881676Sjpk devmap_t *devmapp; 7891676Sjpk strentry_t *tail_str; 7901676Sjpk strentry_t *tmp_str; 7911676Sjpk 7921676Sjpk if (dargs->optflag & DA_MAPS_ONLY) 7931676Sjpk goto dmap_only; 7941676Sjpk 7951676Sjpk /* build device_allocate */ 7961676Sjpk setdaent(); 7971676Sjpk while ((devallocp = getdaent()) != NULL) { 7981676Sjpk rc = da_match(devallocp, dargs); 7991676Sjpk if (rc && dargs->optflag & DA_ADD && 8001676Sjpk !(dargs->optflag & DA_FORCE)) { 8011676Sjpk /* 8021676Sjpk * During DA_ADD, we keep an existing entry unless 8031676Sjpk * we have DA_FORCE set to override that entry. 8041676Sjpk */ 8051676Sjpk dargs->optflag |= DA_NO_OVERRIDE; 8061676Sjpk rc = 0; 8071676Sjpk } 8081676Sjpk if (rc == 0) { 8091676Sjpk tmp_str = _da2strentry(dargs, devallocp); 8101676Sjpk if (tmp_str == NULL) { 8111676Sjpk freedaent(devallocp); 8121676Sjpk enddaent(); 8131676Sjpk return (2); 8141676Sjpk } 8151676Sjpk /* retaining devalloc entry: tmp_str->se_str */ 8161676Sjpk tmp_str->se_next = NULL; 8171676Sjpk if (*head_devallocp == NULL) { 8181676Sjpk *head_devallocp = tail_str = tmp_str; 8191676Sjpk } else { 8201676Sjpk tail_str->se_next = tmp_str; 8211676Sjpk tail_str = tmp_str; 8221676Sjpk } 8231676Sjpk } 8241676Sjpk freedaent(devallocp); 8251676Sjpk } 8261676Sjpk enddaent(); 8271676Sjpk 8281676Sjpk dmap_only: 8291676Sjpk if (dargs->optflag & DA_ALLOC_ONLY) 8301676Sjpk return (rc); 8311676Sjpk 8321676Sjpk /* build device_maps */ 8331676Sjpk rc = 0; 8341676Sjpk setdmapent(); 8351676Sjpk while ((devmapp = getdmapent()) != NULL) { 8361676Sjpk rc = dm_match(devmapp, dargs); 8371676Sjpk if (rc && dargs->optflag & DA_ADD && 8381676Sjpk !(dargs->optflag & DA_FORCE)) { 8391676Sjpk /* 8401676Sjpk * During DA_ADD, we keep an existing entry unless 8411676Sjpk * we have DA_FORCE set to override that entry. 8421676Sjpk */ 8431676Sjpk dargs->optflag |= DA_NO_OVERRIDE; 8441676Sjpk rc = 0; 8451676Sjpk } 8461676Sjpk if (rc == 0) { 847*11529SJan.Parcel@Sun.COM tmp_str = _dmap2strentry(devmapp); 8481676Sjpk if (tmp_str == NULL) { 8491676Sjpk freedmapent(devmapp); 8501676Sjpk enddmapent(); 8511676Sjpk return (2); 8521676Sjpk } 8531676Sjpk /* retaining devmap entry: tmp_str->se_str */ 8541676Sjpk tmp_str->se_next = NULL; 8551676Sjpk if (*head_devmapp == NULL) { 8561676Sjpk *head_devmapp = tail_str = tmp_str; 8571676Sjpk } else { 8581676Sjpk tail_str->se_next = tmp_str; 8591676Sjpk tail_str = tmp_str; 8601676Sjpk } 8611676Sjpk } 8621676Sjpk freedmapent(devmapp); 8631676Sjpk } 8641676Sjpk enddmapent(); 8651676Sjpk 8661676Sjpk return (rc); 8671676Sjpk } 8681676Sjpk 8691676Sjpk /* 8701676Sjpk * _write_defattrs 8711676Sjpk * writes current entries to devalloc_defaults. 8721676Sjpk */ 8731676Sjpk static void 8741676Sjpk _write_defattrs(FILE *fp, strentry_t *head_defent) 8751676Sjpk { 8761676Sjpk strentry_t *tmp_str; 8771676Sjpk 8781676Sjpk for (tmp_str = head_defent; tmp_str != NULL; 8791676Sjpk tmp_str = tmp_str->se_next) { 8801676Sjpk (void) fputs(tmp_str->se_str, fp); 8811676Sjpk (void) fputs("\n", fp); 8821676Sjpk } 8831676Sjpk 8841676Sjpk } 8851676Sjpk 8861676Sjpk /* 8871676Sjpk * _write_device_allocate - 8881676Sjpk * writes current entries in the list to device_allocate. 889*11529SJan.Parcel@Sun.COM * frees the strings 8901676Sjpk */ 8911676Sjpk static void 8921676Sjpk _write_device_allocate(char *odevalloc, FILE *dafp, strentry_t *head_devallocp) 8931676Sjpk { 8941676Sjpk int is_on = -1; 895*11529SJan.Parcel@Sun.COM strentry_t *tmp_str, *old_str; 8961676Sjpk struct stat dastat; 8971676Sjpk 8981676Sjpk (void) fseek(dafp, (off_t)0, SEEK_SET); 8991676Sjpk 9001676Sjpk /* 9011676Sjpk * if the devalloc on/off string existed before, 9021676Sjpk * put it back before anything else. 9031676Sjpk * we need to check for the string only if the file 9041676Sjpk * exists. 9051676Sjpk */ 9061676Sjpk if (stat(odevalloc, &dastat) == 0) { 9071676Sjpk is_on = da_is_on(); 9081676Sjpk if (is_on == 0) 9091676Sjpk (void) fputs(DA_OFF_STR, dafp); 9101676Sjpk else if (is_on == 1) 9111676Sjpk (void) fputs(DA_ON_STR, dafp); 9121676Sjpk } 9131676Sjpk tmp_str = head_devallocp; 9141676Sjpk while (tmp_str) { 9151676Sjpk (void) fputs(tmp_str->se_str, dafp); 9161676Sjpk (void) fputs("\n", dafp); 917*11529SJan.Parcel@Sun.COM old_str = tmp_str; 9181676Sjpk tmp_str = tmp_str->se_next; 919*11529SJan.Parcel@Sun.COM free(old_str); 9201676Sjpk } 9211676Sjpk } 9221676Sjpk 9231676Sjpk /* 9241676Sjpk * _write_device_maps - 9251676Sjpk * writes current entries in the list to device_maps. 926*11529SJan.Parcel@Sun.COM * and frees the strings 9271676Sjpk */ 9281676Sjpk static void 9291676Sjpk _write_device_maps(FILE *dmfp, strentry_t *head_devmapp) 9301676Sjpk { 931*11529SJan.Parcel@Sun.COM strentry_t *tmp_str, *old_str; 9321676Sjpk 9331676Sjpk (void) fseek(dmfp, (off_t)0, SEEK_SET); 9341676Sjpk 9351676Sjpk tmp_str = head_devmapp; 9361676Sjpk while (tmp_str) { 9371676Sjpk (void) fputs(tmp_str->se_str, dmfp); 9381676Sjpk (void) fputs("\n", dmfp); 939*11529SJan.Parcel@Sun.COM old_str = tmp_str; 9401676Sjpk tmp_str = tmp_str->se_next; 941*11529SJan.Parcel@Sun.COM free(old_str); 9421676Sjpk } 9431676Sjpk } 9441676Sjpk 9451676Sjpk /* 9461676Sjpk * _write_new_defattrs 9471676Sjpk * writes the new entry to devalloc_defaults. 9481676Sjpk * returns 0 on success, -1 on error. 9491676Sjpk */ 9501676Sjpk static int 9511676Sjpk _write_new_defattrs(FILE *fp, da_args *dargs) 9521676Sjpk { 9531676Sjpk int count; 9541676Sjpk char *tok = NULL, *tokp = NULL; 9551676Sjpk char *lasts; 9561676Sjpk devinfo_t *devinfo = dargs->devinfo; 9571676Sjpk 9581676Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 9591676Sjpk return (-1); 9601676Sjpk if (!devinfo->devopts) 9611676Sjpk return (0); 9621676Sjpk (void) fprintf(fp, "%s%s", (devinfo->devtype ? devinfo->devtype : ""), 9631676Sjpk KV_TOKEN_DELIMIT); 964*11529SJan.Parcel@Sun.COM if ((tokp = (char *)malloc(strlen(devinfo->devopts) +1)) != NULL) { 9651676Sjpk (void) strcpy(tokp, devinfo->devopts); 9661676Sjpk if ((tok = strtok_r(tokp, KV_DELIMITER, &lasts)) != NULL) { 9671676Sjpk (void) fprintf(fp, "%s", tok); 9681676Sjpk count = 1; 9691676Sjpk } 9701676Sjpk while ((tok = strtok_r(NULL, KV_DELIMITER, &lasts)) != NULL) { 9711676Sjpk if (count) 9721676Sjpk (void) fprintf(fp, "%s", KV_DELIMITER); 9731676Sjpk (void) fprintf(fp, "%s", tok); 9741676Sjpk count++; 9751676Sjpk } 9761676Sjpk } else { 9771676Sjpk (void) fprintf(fp, "%s", devinfo->devopts); 9781676Sjpk } 9791676Sjpk 9801676Sjpk return (0); 9811676Sjpk } 9821676Sjpk 9831676Sjpk /* 9841676Sjpk * _write_new_entry - 9851676Sjpk * writes the new devalloc_t to device_allocate or the new devmap_t to 9861676Sjpk * device_maps. 9871676Sjpk * returns 0 on success, -1 on error. 9881676Sjpk */ 9891676Sjpk static int 9901676Sjpk _write_new_entry(FILE *fp, da_args *dargs, int flag) 9911676Sjpk { 9921676Sjpk int count; 9931676Sjpk char *tok = NULL, *tokp = NULL; 9941676Sjpk char *lasts; 9951676Sjpk devinfo_t *devinfo = dargs->devinfo; 9961676Sjpk 9971676Sjpk if (flag & DA_MAPS_ONLY) 9981676Sjpk goto dmap_only; 9991676Sjpk 10001676Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 10011676Sjpk return (-1); 10021676Sjpk 10031676Sjpk (void) fprintf(fp, "%s%s\\\n\t", 10041676Sjpk (devinfo->devname ? devinfo->devname : ""), KV_DELIMITER); 10051676Sjpk (void) fprintf(fp, "%s%s\\\n\t", 10061676Sjpk (devinfo->devtype ? devinfo->devtype : ""), KV_DELIMITER); 10071676Sjpk if (devinfo->devopts == NULL) { 10081676Sjpk (void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED, 10091676Sjpk KV_DELIMITER); 10101676Sjpk } else { 1011*11529SJan.Parcel@Sun.COM if ((tokp = (char *)malloc(strlen(devinfo->devopts) + 1)) 1012*11529SJan.Parcel@Sun.COM != NULL) { 10131676Sjpk (void) strcpy(tokp, devinfo->devopts); 10141676Sjpk if ((tok = strtok_r(tokp, KV_TOKEN_DELIMIT, &lasts)) != 10151676Sjpk NULL) { 10161676Sjpk (void) fprintf(fp, "%s", tok); 10171676Sjpk count = 1; 10181676Sjpk } 10191676Sjpk while ((tok = strtok_r(NULL, KV_TOKEN_DELIMIT, 10201676Sjpk &lasts)) != NULL) { 10211676Sjpk if (count) 10221676Sjpk (void) fprintf(fp, "%s", 10231676Sjpk KV_TOKEN_DELIMIT "\\\n\t"); 10241676Sjpk (void) fprintf(fp, "%s", tok); 10251676Sjpk count++; 10261676Sjpk } 10271676Sjpk if (count) 10281676Sjpk (void) fprintf(fp, "%s", 10291676Sjpk KV_DELIMITER "\\\n\t"); 10301676Sjpk } else { 10311676Sjpk (void) fprintf(fp, "%s%s", devinfo->devopts, 10321676Sjpk KV_DELIMITER "\\\n\t"); 10331676Sjpk } 10341676Sjpk } 10351676Sjpk (void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED, KV_DELIMITER); 10361676Sjpk (void) fprintf(fp, "%s%s\\\n\t", 10371676Sjpk (devinfo->devauths ? devinfo->devauths : DA_ANYUSER), 10381676Sjpk KV_DELIMITER); 10391676Sjpk (void) fprintf(fp, "%s\n", 10401676Sjpk (devinfo->devexec ? devinfo->devexec : KV_DELIMITER)); 10411676Sjpk 10421676Sjpk dmap_only: 10431676Sjpk if (flag & DA_ALLOC_ONLY) 10441676Sjpk return (0); 10451676Sjpk 10461676Sjpk if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1) 10471676Sjpk return (-1); 10481676Sjpk 10491676Sjpk (void) fprintf(fp, "%s%s\\\n", 10501676Sjpk (devinfo->devname ? devinfo->devname : ""), KV_TOKEN_DELIMIT); 10511676Sjpk (void) fprintf(fp, "\t%s%s\\\n", 10521676Sjpk (devinfo->devtype ? devinfo->devtype : ""), KV_TOKEN_DELIMIT); 10531676Sjpk (void) fprintf(fp, "\t%s\n", 10541676Sjpk (devinfo->devlist ? devinfo->devlist : KV_TOKEN_DELIMIT)); 10551676Sjpk 10561676Sjpk return (0); 10571676Sjpk } 10581676Sjpk 10591676Sjpk /* 10601676Sjpk * _da_lock_devdb - 10611676Sjpk * locks the database files; lock can be either broken explicitly by 10621676Sjpk * closing the fd of the lock file, or it expires automatically at process 10631676Sjpk * termination. 10641676Sjpk * returns fd of the lock file or -1 on error. 10651676Sjpk */ 10661676Sjpk int 10671676Sjpk _da_lock_devdb(char *rootdir) 10681676Sjpk { 10691676Sjpk int lockfd = -1; 10704514Saj int ret; 10714514Saj int count = 0; 10724514Saj int retry = 10; 10734514Saj int retry_sleep; 10744514Saj uint_t seed; 10751676Sjpk char *lockfile; 10761676Sjpk char path[MAXPATHLEN]; 10771676Sjpk int size = sizeof (path); 10781676Sjpk 10791676Sjpk if (rootdir == NULL) { 10801676Sjpk lockfile = DA_DB_LOCK; 10811676Sjpk } else { 10821676Sjpk path[0] = '\0'; 10831676Sjpk if (snprintf(path, size, "%s%s", rootdir, DA_DB_LOCK) >= size) 10841676Sjpk return (-1); 10851676Sjpk lockfile = path; 10861676Sjpk } 10871676Sjpk 10881676Sjpk if ((lockfd = open(lockfile, O_RDWR | O_CREAT, 0600)) == -1) 10891676Sjpk /* cannot open lock file */ 10901676Sjpk return (-1); 10911676Sjpk 10921676Sjpk (void) fchown(lockfd, DA_UID, DA_GID); 10931676Sjpk 10941676Sjpk if (lseek(lockfd, (off_t)0, SEEK_SET) == -1) { 10951676Sjpk /* cannot position lock file */ 10961676Sjpk (void) close(lockfd); 10971676Sjpk return (-1); 10981676Sjpk } 10994514Saj errno = 0; 11004514Saj while (retry > 0) { 11014514Saj count++; 11024514Saj seed = (uint_t)gethrtime(); 11034514Saj ret = lockf(lockfd, F_TLOCK, 0); 11044514Saj if (ret == 0) { 11054514Saj (void) utime(lockfile, NULL); 11064514Saj return (lockfd); 11074514Saj } 11084514Saj if ((errno != EACCES) && (errno != EAGAIN)) { 11094514Saj /* cannot set lock */ 11104514Saj (void) close(lockfd); 11114514Saj return (-1); 11124514Saj } 11134514Saj retry--; 11144514Saj retry_sleep = rand_r(&seed)/((RAND_MAX + 2)/3) + count; 11154514Saj (void) sleep(retry_sleep); 11164514Saj errno = 0; 11171676Sjpk } 11181676Sjpk 11194514Saj return (-1); 11201676Sjpk } 11211676Sjpk 11221676Sjpk /* 11231676Sjpk * da_open_devdb - 11241676Sjpk * opens one or both database files - device_allocate, device_maps - in 11251676Sjpk * the specified mode. 11261676Sjpk * locks the database files; lock is either broken explicitly by the 11271676Sjpk * caller by closing the lock file fd, or it expires automatically at 11281676Sjpk * process termination. 11291676Sjpk * writes the file pointer of opened file in the input args - dafp, dmfp. 11301676Sjpk * returns fd of the lock file on success, -2 if database file does not 11311676Sjpk * exist, -1 on other errors. 11321676Sjpk */ 11331676Sjpk int 11341676Sjpk da_open_devdb(char *rootdir, FILE **dafp, FILE **dmfp, int flag) 11351676Sjpk { 11361676Sjpk int oflag = 0; 11371676Sjpk int fda = -1; 11381676Sjpk int fdm = -1; 11391676Sjpk int lockfd = -1; 11401676Sjpk char *fname; 11411676Sjpk char *fmode; 11421676Sjpk char path[MAXPATHLEN]; 11431676Sjpk FILE *devfile; 11441676Sjpk 11451676Sjpk if ((dafp == NULL) && (dmfp == NULL)) 11461676Sjpk return (-1); 11471676Sjpk 11481676Sjpk if (flag & DA_RDWR) { 11491676Sjpk oflag = DA_RDWR; 11501914Scasper fmode = "r+F"; 11511676Sjpk } else if (flag & DA_RDONLY) { 11521676Sjpk oflag = DA_RDONLY; 11531914Scasper fmode = "rF"; 11541676Sjpk } 11551676Sjpk 11561676Sjpk if ((lockfd = _da_lock_devdb(rootdir)) == -1) 11571676Sjpk return (-1); 11581676Sjpk 11591676Sjpk if ((dafp == NULL) || (flag & DA_MAPS_ONLY)) 11601676Sjpk goto dmap_only; 11611676Sjpk 11621676Sjpk path[0] = '\0'; 11631676Sjpk 11641676Sjpk /* 11651676Sjpk * open the device allocation file 11661676Sjpk */ 11671676Sjpk if (rootdir == NULL) { 11681676Sjpk fname = DEVALLOC; 11691676Sjpk } else { 11701676Sjpk if (snprintf(path, sizeof (path), "%s%s", rootdir, 11711676Sjpk DEVALLOC) >= sizeof (path)) { 11721676Sjpk if (lockfd != -1) 11731676Sjpk (void) close(lockfd); 11741676Sjpk return (-1); 11751676Sjpk } 11761676Sjpk fname = path; 11771676Sjpk } 11781676Sjpk if ((fda = open(fname, oflag, DA_DBMODE)) == -1) { 11791676Sjpk if (lockfd != -1) 11801676Sjpk (void) close(lockfd); 11811676Sjpk return ((errno == ENOENT) ? -2 : -1); 11821676Sjpk } 11831676Sjpk if ((devfile = fdopen(fda, fmode)) == NULL) { 11841676Sjpk (void) close(fda); 11851676Sjpk if (lockfd != -1) 11861676Sjpk (void) close(lockfd); 11871676Sjpk return (-1); 11881676Sjpk } 11891676Sjpk *dafp = devfile; 11901676Sjpk (void) fchmod(fda, DA_DBMODE); 11911676Sjpk 11921676Sjpk if ((flag & DA_ALLOC_ONLY)) 11931676Sjpk goto out; 11941676Sjpk 11951676Sjpk dmap_only: 11961676Sjpk path[0] = '\0'; 11971676Sjpk /* 11981676Sjpk * open the device map file 11991676Sjpk */ 12001676Sjpk if (rootdir == NULL) { 12011676Sjpk fname = DEVMAP; 12021676Sjpk } else { 12031676Sjpk if (snprintf(path, sizeof (path), "%s%s", rootdir, 12041676Sjpk DEVMAP) >= sizeof (path)) { 12051676Sjpk (void) close(fda); 12061676Sjpk if (lockfd != -1) 12071676Sjpk (void) close(lockfd); 12081676Sjpk return (-1); 12091676Sjpk } 12101676Sjpk fname = path; 12111676Sjpk } 12121676Sjpk 12131676Sjpk if ((fdm = open(fname, oflag, DA_DBMODE)) == -1) { 12141676Sjpk if (lockfd != -1) 12151676Sjpk (void) close(lockfd); 12161676Sjpk return ((errno == ENOENT) ? -2 : -1); 12171676Sjpk } 12181676Sjpk 12191676Sjpk if ((devfile = fdopen(fdm, fmode)) == NULL) { 12201676Sjpk (void) close(fdm); 12211676Sjpk (void) close(fda); 12221676Sjpk if (lockfd != -1) 12231676Sjpk (void) close(lockfd); 12241676Sjpk return (-1); 12251676Sjpk } 12261676Sjpk *dmfp = devfile; 12271676Sjpk (void) fchmod(fdm, DA_DBMODE); 12281676Sjpk 12291676Sjpk out: 12301676Sjpk return (lockfd); 12311676Sjpk } 12321676Sjpk 12331676Sjpk /* 12341676Sjpk * _record_on_off - 12351676Sjpk * adds either DA_ON_STR or DA_OFF_STR to device_allocate 12361676Sjpk * returns 0 on success, -1 on error. 12371676Sjpk */ 12381676Sjpk static int 12391676Sjpk _record_on_off(da_args *dargs, FILE *tafp, FILE *dafp) 12401676Sjpk { 12411676Sjpk int dafd; 12421676Sjpk int nsize; 12431676Sjpk int nitems = 1; 12441676Sjpk int actionlen; 12451676Sjpk int str_found = 0; 12461676Sjpk int len = 0, nlen = 0, plen = 0; 12471676Sjpk char *ptr = NULL; 12481676Sjpk char *actionstr; 12491676Sjpk char *nbuf = NULL; 12501676Sjpk char line[MAX_CANON]; 12511676Sjpk struct stat dastat; 12521676Sjpk 12531676Sjpk if (dargs->optflag & DA_ON) 12541676Sjpk actionstr = DA_ON_STR; 12551676Sjpk else 12561676Sjpk actionstr = DA_OFF_STR; 12571676Sjpk actionlen = strlen(actionstr); 12581676Sjpk dafd = fileno(dafp); 12591676Sjpk if (fstat(dafd, &dastat) == -1) 12601676Sjpk return (-1); 12611676Sjpk 12621676Sjpk /* check the old device_allocate for on/off string */ 12631676Sjpk ptr = fgets(line, MAX_CANON, dafp); 12641676Sjpk if (ptr != NULL) { 12651676Sjpk if ((strcmp(line, DA_ON_STR) == 0) || 12661676Sjpk (strcmp(line, DA_OFF_STR) == 0)) { 12671676Sjpk str_found = 1; 12681676Sjpk nsize = dastat.st_size; 12691676Sjpk } 12701676Sjpk } 12711676Sjpk if (!ptr || !str_found) { 12721676Sjpk /* 12731676Sjpk * the file never had either the on or the off string; 12741676Sjpk * make room for it. 12751676Sjpk */ 12761676Sjpk str_found = 0; 12771676Sjpk nsize = dastat.st_size + actionlen + 1; 12781676Sjpk } 1279*11529SJan.Parcel@Sun.COM if ((nbuf = (char *)malloc(nsize + 1)) == NULL) 12801676Sjpk return (-1); 12811676Sjpk nbuf[0] = '\0'; 12821676Sjpk /* put the on/off string */ 12831676Sjpk (void) strcpy(nbuf, actionstr); 12841676Sjpk nlen = strlen(nbuf); 12851676Sjpk plen = nlen; 12861676Sjpk if (ptr && !str_found) { 12871676Sjpk /* now put the first line that we read in fgets */ 12881676Sjpk nlen = plen + strlen(line) + 1; 12891676Sjpk len = snprintf(nbuf + plen, nlen - plen, "%s", line); 12901676Sjpk if (len >= nsize) { 12911676Sjpk free(nbuf); 12921676Sjpk return (-1); 12931676Sjpk } 12941676Sjpk plen += len; 12951676Sjpk } 12961676Sjpk 12971676Sjpk /* now get the rest of the old file */ 12981676Sjpk while (fgets(line, MAX_CANON, dafp) != NULL) { 12991676Sjpk nlen = plen + strlen(line) + 1; 13001676Sjpk len = snprintf(nbuf + plen, nlen - plen, "%s", line); 13011676Sjpk if (len >= nsize) { 13021676Sjpk free(nbuf); 13031676Sjpk return (-1); 13041676Sjpk } 13051676Sjpk plen += len; 13061676Sjpk } 13071676Sjpk len = strlen(nbuf) + 1; 13081676Sjpk if (len < nsize) 13091676Sjpk nbuf[len] = '\n'; 13101676Sjpk 13111676Sjpk /* write the on/off str + the old device_allocate to the temp file */ 13121676Sjpk if (fwrite(nbuf, nsize, nitems, tafp) < nitems) { 13131676Sjpk free(nbuf); 13141676Sjpk return (-1); 13151676Sjpk } 13161676Sjpk 13171676Sjpk free(nbuf); 13181676Sjpk 13191676Sjpk return (0); 13201676Sjpk } 13211676Sjpk 13221676Sjpk /* 13231676Sjpk * da_update_defattrs - 13241676Sjpk * writes default attributes to devalloc_defaults 13251676Sjpk * returns 0 on success, -1 on error. 13261676Sjpk */ 13271676Sjpk int 13281676Sjpk da_update_defattrs(da_args *dargs) 13291676Sjpk { 13301676Sjpk int rc = 0, lockfd = 0, tmpfd = 0; 13311676Sjpk char *defpath = DEFATTRS; 13321676Sjpk char *tmpdefpath = TMPATTRS; 13331676Sjpk FILE *tmpfp = NULL; 13341676Sjpk struct stat dstat; 13351676Sjpk strentry_t *head_defent = NULL; 13361676Sjpk 13371676Sjpk if (dargs == NULL) 13381676Sjpk return (0); 13391676Sjpk if ((lockfd = _da_lock_devdb(NULL)) == -1) 13401676Sjpk return (-1); 13411676Sjpk if ((tmpfd = open(tmpdefpath, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 13421676Sjpk (void) close(lockfd); 13431676Sjpk return (-1); 13441676Sjpk } 13451676Sjpk (void) fchown(tmpfd, DA_UID, DA_GID); 13461676Sjpk if ((tmpfp = fdopen(tmpfd, "r+")) == NULL) { 13471676Sjpk (void) close(tmpfd); 13481676Sjpk (void) unlink(tmpdefpath); 13491676Sjpk (void) close(lockfd); 13501676Sjpk return (-1); 13511676Sjpk } 13521676Sjpk /* 13531676Sjpk * examine all entries, remove an old one if required, check 13541676Sjpk * if a new one needs to be added. 13551676Sjpk */ 13561676Sjpk if (stat(defpath, &dstat) == 0) { 13571676Sjpk if ((rc = _build_defattrs(dargs, &head_defent)) != 0) { 13581676Sjpk if (rc == 1) { 13591676Sjpk (void) close(tmpfd); 13601676Sjpk (void) unlink(tmpdefpath); 13611676Sjpk (void) close(lockfd); 13621676Sjpk return (rc); 13631676Sjpk } 13641676Sjpk } 13651676Sjpk } 13661676Sjpk /* 13671676Sjpk * write back any existing entries. 13681676Sjpk */ 13691676Sjpk _write_defattrs(tmpfp, head_defent); 13701676Sjpk 13711676Sjpk if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) { 13721676Sjpk /* add new entries */ 13731676Sjpk rc = _write_new_defattrs(tmpfp, dargs); 13741676Sjpk (void) fclose(tmpfp); 13751676Sjpk } else { 13761676Sjpk (void) fclose(tmpfp); 13771676Sjpk } 13781676Sjpk if (rename(tmpdefpath, defpath) != 0) { 13791676Sjpk rc = -1; 13801676Sjpk (void) unlink(tmpdefpath); 13811676Sjpk } 13821676Sjpk (void) close(lockfd); 13831676Sjpk 13841676Sjpk return (rc); 13851676Sjpk } 13861676Sjpk 13871676Sjpk /* 13881676Sjpk * da_update_device - 1389*11529SJan.Parcel@Sun.COM * Writes existing entries and the SINGLE change requested by da_args, 1390*11529SJan.Parcel@Sun.COM * to device_allocate and device_maps. 1391*11529SJan.Parcel@Sun.COM * Returns 0 on success, -1 on error. 13921676Sjpk */ 13931676Sjpk int 13941676Sjpk da_update_device(da_args *dargs) 13951676Sjpk { 13961676Sjpk int rc; 13971676Sjpk int tafd = -1, tmfd = -1; 13981676Sjpk int lockfd = -1; 13991676Sjpk char *rootdir = NULL; 14004514Saj char *apathp = NULL, *mpathp = NULL; 14014514Saj char *dapathp = NULL, *dmpathp = NULL; 14024514Saj char apath[MAXPATHLEN], mpath[MAXPATHLEN]; 14034514Saj char dapath[MAXPATHLEN], dmpath[MAXPATHLEN]; 14041676Sjpk FILE *tafp = NULL, *tmfp = NULL, *dafp = NULL; 14051676Sjpk struct stat dastat; 14061676Sjpk devinfo_t *devinfo; 14071676Sjpk strentry_t *head_devmapp = NULL; 14081676Sjpk strentry_t *head_devallocp = NULL; 14091676Sjpk 14101676Sjpk if (dargs == NULL) 14111676Sjpk return (0); 14121676Sjpk 14131676Sjpk rootdir = dargs->rootdir; 14141676Sjpk devinfo = dargs->devinfo; 14151676Sjpk 14161676Sjpk /* 14171676Sjpk * adding/removing entries should be done in both 14181676Sjpk * device_allocate and device_maps. updates can be 14191676Sjpk * done in both or either of the files. 14201676Sjpk */ 14211676Sjpk if (dargs->optflag & DA_ADD || dargs->optflag & DA_REMOVE) { 14221676Sjpk if (dargs->optflag & DA_ALLOC_ONLY || 14231676Sjpk dargs->optflag & DA_MAPS_ONLY) 14241676Sjpk return (0); 14251676Sjpk } 14261676Sjpk 14271676Sjpk /* 14281676Sjpk * name, type and list are required fields for adding a new 14291676Sjpk * device. 14301676Sjpk */ 14311676Sjpk if ((dargs->optflag & DA_ADD) && 14321676Sjpk ((devinfo->devname == NULL) || 14331676Sjpk (devinfo->devtype == NULL) || 14341676Sjpk (devinfo->devlist == NULL))) { 14351676Sjpk return (-1); 14361676Sjpk } 14371676Sjpk 14381676Sjpk if (rootdir != NULL) { 14391676Sjpk if (snprintf(apath, sizeof (apath), "%s%s", rootdir, 14401676Sjpk TMPALLOC) >= sizeof (apath)) 14411676Sjpk return (-1); 14421676Sjpk apathp = apath; 14431676Sjpk if (snprintf(dapath, sizeof (dapath), "%s%s", rootdir, 14441676Sjpk DEVALLOC) >= sizeof (dapath)) 14451676Sjpk return (-1); 14461676Sjpk dapathp = dapath; 14471676Sjpk if (!(dargs->optflag & DA_ALLOC_ONLY)) { 14481676Sjpk if (snprintf(mpath, sizeof (mpath), "%s%s", rootdir, 14491676Sjpk TMPMAP) >= sizeof (mpath)) 14501676Sjpk return (-1); 14511676Sjpk mpathp = mpath; 14521676Sjpk if (snprintf(dmpath, sizeof (dmpath), "%s%s", rootdir, 14531676Sjpk DEVMAP) >= sizeof (dmpath)) 14541676Sjpk return (-1); 14551676Sjpk dmpathp = dmpath; 14561676Sjpk } 14571676Sjpk } else { 14581676Sjpk apathp = TMPALLOC; 14591676Sjpk dapathp = DEVALLOC; 14601676Sjpk mpathp = TMPMAP; 14611676Sjpk dmpathp = DEVMAP; 14621676Sjpk } 14631676Sjpk 14641676Sjpk if (dargs->optflag & DA_MAPS_ONLY) 14651676Sjpk goto dmap_only; 14661676Sjpk 14671676Sjpk /* 14681676Sjpk * Check if we are here just to record on/off status of 14691676Sjpk * device_allocation. 14701676Sjpk */ 14711676Sjpk if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) 14721676Sjpk lockfd = da_open_devdb(dargs->rootdir, &dafp, NULL, 14731676Sjpk DA_RDONLY|DA_ALLOC_ONLY); 14741676Sjpk else 14751676Sjpk lockfd = _da_lock_devdb(rootdir); 14761676Sjpk if (lockfd == -1) 14771676Sjpk return (-1); 14781676Sjpk 14791676Sjpk if ((tafd = open(apathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 14801676Sjpk (void) close(lockfd); 14811676Sjpk (void) fclose(dafp); 14821676Sjpk return (-1); 14831676Sjpk } 14841676Sjpk (void) fchown(tafd, DA_UID, DA_GID); 14851676Sjpk if ((tafp = fdopen(tafd, "r+")) == NULL) { 14861676Sjpk (void) close(tafd); 14871676Sjpk (void) unlink(apathp); 14881676Sjpk (void) fclose(dafp); 14891676Sjpk (void) close(lockfd); 14901676Sjpk return (-1); 14911676Sjpk } 14921676Sjpk 14931676Sjpk /* 14941676Sjpk * We don't need to parse the file if we are here just to record 14951676Sjpk * on/off status of device_allocation. 14961676Sjpk */ 14971676Sjpk if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) { 14981676Sjpk if (_record_on_off(dargs, tafp, dafp) == -1) { 14991676Sjpk (void) close(tafd); 15001676Sjpk (void) unlink(apathp); 15011676Sjpk (void) fclose(dafp); 15021676Sjpk (void) close(lockfd); 15031676Sjpk return (-1); 15041676Sjpk } 15051676Sjpk (void) fclose(dafp); 15061676Sjpk goto out; 15071676Sjpk } 15081676Sjpk 15091676Sjpk /* 1510*11529SJan.Parcel@Sun.COM * If reacting to a hotplug, read the file entries, 1511*11529SJan.Parcel@Sun.COM * figure out what dname (tname + a new number) goes to the 1512*11529SJan.Parcel@Sun.COM * device being added/removed, and create a good head_devallocp and 1513*11529SJan.Parcel@Sun.COM * head_devmapp with everything good still in it (_rebuild_lists) 1514*11529SJan.Parcel@Sun.COM * 1515*11529SJan.Parcel@Sun.COM * Else examine all the entries, remove an old one if it is 1516*11529SJan.Parcel@Sun.COM * a duplicate with a device being added, returning the 1517*11529SJan.Parcel@Sun.COM * remaining list (_build_lists.) 1518*11529SJan.Parcel@Sun.COM * 1519*11529SJan.Parcel@Sun.COM * We need to do this only if the file exists already. 1520*11529SJan.Parcel@Sun.COM * 1521*11529SJan.Parcel@Sun.COM * Once we have built these lists, we need to free the strings 1522*11529SJan.Parcel@Sun.COM * in the head_* arrays before returning. 15231676Sjpk */ 15241676Sjpk if (stat(dapathp, &dastat) == 0) { 1525*11529SJan.Parcel@Sun.COM /* for device allocation, the /etc files are the "master" */ 1526*11529SJan.Parcel@Sun.COM if ((dargs->optflag & (DA_ADD| DA_EVENT)) && 1527*11529SJan.Parcel@Sun.COM (!(dargs->optflag & DA_FORCE))) 1528*11529SJan.Parcel@Sun.COM rc = _rebuild_lists(dargs, &head_devallocp, 1529*11529SJan.Parcel@Sun.COM &head_devmapp); 1530*11529SJan.Parcel@Sun.COM else 1531*11529SJan.Parcel@Sun.COM rc = _build_lists(dargs, &head_devallocp, 1532*11529SJan.Parcel@Sun.COM &head_devmapp); 1533*11529SJan.Parcel@Sun.COM 1534*11529SJan.Parcel@Sun.COM if (rc != 0 && rc != 1) { 1535*11529SJan.Parcel@Sun.COM (void) close(tafd); 1536*11529SJan.Parcel@Sun.COM (void) unlink(apathp); 1537*11529SJan.Parcel@Sun.COM (void) close(lockfd); 1538*11529SJan.Parcel@Sun.COM return (-1); 15391676Sjpk } 1540*11529SJan.Parcel@Sun.COM } else 1541*11529SJan.Parcel@Sun.COM rc = 0; 1542*11529SJan.Parcel@Sun.COM 1543*11529SJan.Parcel@Sun.COM if ((dargs->optflag & DA_REMOVE) && (rc == 0)) { 1544*11529SJan.Parcel@Sun.COM (void) close(tafd); 1545*11529SJan.Parcel@Sun.COM (void) unlink(apathp); 1546*11529SJan.Parcel@Sun.COM (void) close(lockfd); 1547*11529SJan.Parcel@Sun.COM return (0); 15481676Sjpk } 1549*11529SJan.Parcel@Sun.COM /* 1550*11529SJan.Parcel@Sun.COM * TODO: clean up the workings of DA_UPDATE. 1551*11529SJan.Parcel@Sun.COM * Due to da_match looking at fields that are missing 1552*11529SJan.Parcel@Sun.COM * in dargs for DA_UPDATE, the da_match call returns no match, 1553*11529SJan.Parcel@Sun.COM * but due to the way _da2str combines the devalloc_t info with 1554*11529SJan.Parcel@Sun.COM * the *dargs info, the DA_ADD_ZONE and DA_REMOVE_ZONE work. 1555*11529SJan.Parcel@Sun.COM * 1556*11529SJan.Parcel@Sun.COM * This would not scale if any type of update was ever needed 1557*11529SJan.Parcel@Sun.COM * from the daemon. 1558*11529SJan.Parcel@Sun.COM */ 15591676Sjpk 15601676Sjpk /* 1561*11529SJan.Parcel@Sun.COM * Write out devallocp along with the devalloc on/off string. 15621676Sjpk */ 15631676Sjpk _write_device_allocate(dapathp, tafp, head_devallocp); 15641676Sjpk 15651676Sjpk if (dargs->optflag & DA_ALLOC_ONLY) 15661676Sjpk goto out; 15671676Sjpk 15681676Sjpk dmap_only: 15691676Sjpk if ((tmfd = open(mpathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) { 15701676Sjpk (void) close(tafd); 15711676Sjpk (void) unlink(apathp); 15721676Sjpk (void) close(lockfd); 15731676Sjpk return (-1); 15741676Sjpk } 15751676Sjpk (void) fchown(tmfd, DA_UID, DA_GID); 15761676Sjpk if ((tmfp = fdopen(tmfd, "r+")) == NULL) { 15771676Sjpk (void) close(tafd); 15781676Sjpk (void) unlink(apathp); 15791676Sjpk (void) close(tmfd); 15801676Sjpk (void) unlink(mpathp); 15811676Sjpk (void) close(lockfd); 15821676Sjpk return (-1); 15831676Sjpk } 15841676Sjpk 1585*11529SJan.Parcel@Sun.COM /* 1586*11529SJan.Parcel@Sun.COM * Write back any non-removed pre-existing entries. 1587*11529SJan.Parcel@Sun.COM */ 15881676Sjpk if (head_devmapp != NULL) 15891676Sjpk _write_device_maps(tmfp, head_devmapp); 15901676Sjpk 15911676Sjpk out: 1592*11529SJan.Parcel@Sun.COM /* 1593*11529SJan.Parcel@Sun.COM * Add any new entries here. 1594*11529SJan.Parcel@Sun.COM */ 15951676Sjpk if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) { 15961676Sjpk /* add any new entries */ 15971676Sjpk rc = _write_new_entry(tafp, dargs, DA_ALLOC_ONLY); 15981676Sjpk (void) fclose(tafp); 15991676Sjpk 16001676Sjpk if (rc == 0) 16011676Sjpk rc = _write_new_entry(tmfp, dargs, DA_MAPS_ONLY); 16021676Sjpk (void) fclose(tmfp); 16031676Sjpk } else { 16041676Sjpk if (tafp) 16051676Sjpk (void) fclose(tafp); 16061676Sjpk if (tmfp) 16071676Sjpk (void) fclose(tmfp); 16081676Sjpk } 16091676Sjpk 16101676Sjpk rc = 0; 16111676Sjpk if (!(dargs->optflag & DA_MAPS_ONLY)) { 16121676Sjpk if (rename(apathp, dapathp) != 0) { 16131676Sjpk rc = -1; 16141676Sjpk (void) unlink(apathp); 16151676Sjpk } 16161676Sjpk } 16171676Sjpk if (!(dargs->optflag & DA_ALLOC_ONLY)) { 16181676Sjpk if (rename(mpathp, dmpathp) != 0) { 16191676Sjpk rc = -1; 16201676Sjpk (void) unlink(mpathp); 16211676Sjpk } 16221676Sjpk } 16231676Sjpk 16241676Sjpk (void) close(lockfd); 16251676Sjpk 16261676Sjpk return (rc); 16271676Sjpk } 16281676Sjpk 16291676Sjpk /* 16301676Sjpk * da_add_list - 16311676Sjpk * adds new /dev link name to the linked list of devices. 16321676Sjpk * returns 0 if link added successfully, -1 on error. 16331676Sjpk */ 16341676Sjpk int 16351676Sjpk da_add_list(devlist_t *dlist, char *link, int new_instance, int flag) 16361676Sjpk { 16371676Sjpk int instance; 16381676Sjpk int nlen, plen; 16391676Sjpk int new_entry = 0; 16401676Sjpk char *dtype, *dexec, *tname, *kval; 16411676Sjpk char *minstr = NULL, *maxstr = NULL; 1642*11529SJan.Parcel@Sun.COM char dname[DA_MAXNAME + 1]; 16431676Sjpk kva_t *kva; 16441676Sjpk deventry_t *dentry = NULL, *nentry = NULL, *pentry = NULL; 16451676Sjpk da_defs_t *da_defs; 16461676Sjpk 16471676Sjpk if (dlist == NULL || link == NULL) 16481676Sjpk return (-1); 16491676Sjpk 16501676Sjpk dname[0] = '\0'; 16511676Sjpk if (flag & DA_AUDIO) { 16521676Sjpk dentry = dlist->audio; 16531676Sjpk tname = DA_AUDIO_NAME; 16541676Sjpk dtype = DA_AUDIO_TYPE; 16551676Sjpk dexec = DA_DEFAULT_AUDIO_CLEAN; 16561676Sjpk } else if (flag & DA_CD) { 16571676Sjpk dentry = dlist->cd; 16581676Sjpk tname = DA_CD_NAME; 16591676Sjpk dtype = DA_CD_TYPE; 16601676Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 16611676Sjpk } else if (flag & DA_FLOPPY) { 16621676Sjpk dentry = dlist->floppy; 16631676Sjpk tname = DA_FLOPPY_NAME; 16641676Sjpk dtype = DA_FLOPPY_TYPE; 16651676Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 16661676Sjpk } else if (flag & DA_TAPE) { 16671676Sjpk dentry = dlist->tape; 16681676Sjpk tname = DA_TAPE_NAME; 16691676Sjpk dtype = DA_TAPE_TYPE; 16701676Sjpk dexec = DA_DEFAULT_TAPE_CLEAN; 16711676Sjpk } else if (flag & DA_RMDISK) { 16721676Sjpk dentry = dlist->rmdisk; 16731676Sjpk tname = DA_RMDISK_NAME; 16741676Sjpk dtype = DA_RMDISK_TYPE; 16751676Sjpk dexec = DA_DEFAULT_DISK_CLEAN; 16761676Sjpk } else { 16771676Sjpk return (-1); 16781676Sjpk } 16791676Sjpk 16801676Sjpk for (nentry = dentry; nentry != NULL; nentry = nentry->next) { 16811676Sjpk pentry = nentry; 16821676Sjpk (void) sscanf(nentry->devinfo.devname, "%*[a-z]%d", &instance); 16831676Sjpk if (nentry->devinfo.instance == new_instance) 16841676Sjpk /* 16851676Sjpk * Add the new link name to the list of links 16861676Sjpk * that the device 'dname' has. 16871676Sjpk */ 16881676Sjpk break; 16891676Sjpk } 16901676Sjpk 16911676Sjpk if (nentry == NULL) { 16921676Sjpk /* 16931676Sjpk * Either this is the first entry ever, or no matching entry 16941676Sjpk * was found. Create a new one and add to the list. 16951676Sjpk */ 16961676Sjpk if (dentry == NULL) /* first entry ever */ 16971676Sjpk instance = 0; 16981676Sjpk else /* no matching entry */ 16991676Sjpk instance++; 17001676Sjpk (void) snprintf(dname, sizeof (dname), "%s%d", tname, instance); 17011676Sjpk if ((nentry = (deventry_t *)malloc(sizeof (deventry_t))) == 17021676Sjpk NULL) 17031676Sjpk return (-1); 17041676Sjpk if (pentry != NULL) 17051676Sjpk pentry->next = nentry; 17061676Sjpk new_entry = 1; 17071676Sjpk nentry->devinfo.devname = strdup(dname); 17081676Sjpk nentry->devinfo.devtype = dtype; 17091676Sjpk nentry->devinfo.devauths = DEFAULT_DEV_ALLOC_AUTH; 17101676Sjpk nentry->devinfo.devexec = dexec; 17111676Sjpk nentry->devinfo.instance = new_instance; 17121676Sjpk /* 17131676Sjpk * Look for default label range, authorizations and cleaning 17141676Sjpk * program in devalloc_defaults. If label range is not 17151676Sjpk * specified in devalloc_defaults, assume it to be admin_low 17161676Sjpk * to admin_high. 17171676Sjpk */ 17181676Sjpk minstr = DA_DEFAULT_MIN; 17191676Sjpk maxstr = DA_DEFAULT_MAX; 17201676Sjpk setdadefent(); 17211676Sjpk if (da_defs = getdadeftype(nentry->devinfo.devtype)) { 17221676Sjpk kva = da_defs->devopts; 17231676Sjpk if ((kval = kva_match(kva, DAOPT_MINLABEL)) != NULL) 17241676Sjpk minstr = strdup(kval); 17251676Sjpk if ((kval = kva_match(kva, DAOPT_MAXLABEL)) != NULL) 17261676Sjpk maxstr = strdup(kval); 17271676Sjpk if ((kval = kva_match(kva, DAOPT_AUTHS)) != NULL) 17281676Sjpk nentry->devinfo.devauths = strdup(kval); 17291676Sjpk if ((kval = kva_match(kva, DAOPT_CSCRIPT)) != NULL) 17301676Sjpk nentry->devinfo.devexec = strdup(kval); 17311676Sjpk freedadefent(da_defs); 17321676Sjpk } 17331676Sjpk enddadefent(); 17341676Sjpk kval = NULL; 17351676Sjpk nlen = strlen(DAOPT_MINLABEL) + strlen(KV_ASSIGN) + 17361676Sjpk strlen(minstr) + strlen(KV_TOKEN_DELIMIT) + 17371676Sjpk strlen(DAOPT_MAXLABEL) + strlen(KV_ASSIGN) + strlen(maxstr) 17381676Sjpk + 1; /* +1 for terminator */ 17391676Sjpk if (kval = (char *)malloc(nlen)) 17401676Sjpk (void) snprintf(kval, nlen, "%s%s%s%s%s%s%s", 17411676Sjpk DAOPT_MINLABEL, KV_ASSIGN, minstr, KV_TOKEN_DELIMIT, 17421676Sjpk DAOPT_MAXLABEL, KV_ASSIGN, maxstr); 17431676Sjpk nentry->devinfo.devopts = kval; 17441676Sjpk 17451676Sjpk nentry->devinfo.devlist = NULL; 17461676Sjpk nentry->next = NULL; 17471676Sjpk } 17481676Sjpk 17491676Sjpk nlen = strlen(link) + 1; /* +1 terminator */ 17501676Sjpk if (nentry->devinfo.devlist) { 17511676Sjpk plen = strlen(nentry->devinfo.devlist); 17521676Sjpk nlen = nlen + plen + 1; /* +1 for blank to separate entries */ 17531676Sjpk } else { 17541676Sjpk plen = 0; 17551676Sjpk } 17561676Sjpk 17571676Sjpk if ((nentry->devinfo.devlist = 17581676Sjpk (char *)realloc(nentry->devinfo.devlist, nlen)) == NULL) { 17591676Sjpk if (new_entry) { 17601676Sjpk free(nentry->devinfo.devname); 17611676Sjpk free(nentry); 17621676Sjpk if (pentry != NULL) 17631676Sjpk pentry->next = NULL; 17641676Sjpk } 17651676Sjpk return (-1); 17661676Sjpk } 17671676Sjpk 17681676Sjpk if (plen == 0) 17691676Sjpk (void) snprintf(nentry->devinfo.devlist, nlen, "%s", link); 17701676Sjpk else 17711676Sjpk (void) snprintf(nentry->devinfo.devlist + plen, nlen - plen, 17721676Sjpk " %s", link); 17731676Sjpk 17741676Sjpk if (pentry == NULL) { 17751676Sjpk /* 17761676Sjpk * This is the first entry of this device type. 17771676Sjpk */ 17781676Sjpk if (flag & DA_AUDIO) 17791676Sjpk dlist->audio = nentry; 17801676Sjpk else if (flag & DA_CD) 17811676Sjpk dlist->cd = nentry; 17821676Sjpk else if (flag & DA_FLOPPY) 17831676Sjpk dlist->floppy = nentry; 17841676Sjpk else if (flag & DA_TAPE) 17851676Sjpk dlist->tape = nentry; 17861676Sjpk else if (flag & DA_RMDISK) 17871676Sjpk dlist->rmdisk = nentry; 17881676Sjpk } 17891676Sjpk 17901676Sjpk return (0); 17911676Sjpk } 17921676Sjpk 17931676Sjpk /* 17941676Sjpk * da_remove_list - 17951676Sjpk * removes a /dev link name from the linked list of devices. 17961676Sjpk * returns type of device if link for that device removed 17971676Sjpk * successfully, else returns -1 on error. 17981676Sjpk * if all links for a device are removed, stores that device 17991676Sjpk * name in devname. 18001676Sjpk */ 18011676Sjpk int 18021676Sjpk da_remove_list(devlist_t *dlist, char *link, int type, char *devname, int size) 18031676Sjpk { 18041676Sjpk int flag; 18051676Sjpk int remove_dev = 0; 18061676Sjpk int nlen, plen, slen; 18071676Sjpk char *lasts, *lname, *oldlist; 18081676Sjpk struct stat rmstat; 18091676Sjpk deventry_t *dentry, *current, *prev; 18101676Sjpk 18111676Sjpk if (type != NULL) 18121676Sjpk flag = type; 18131676Sjpk else if (link == NULL) 18141676Sjpk return (-1); 18151676Sjpk else if (strstr(link, DA_AUDIO_NAME) || strstr(link, DA_SOUND_NAME)) 18161676Sjpk flag = DA_AUDIO; 18171676Sjpk else if (strstr(link, "dsk") || strstr(link, "rdsk") || 18181676Sjpk strstr(link, "sr") || strstr(link, "rsr")) 18191676Sjpk flag = DA_CD; 18201676Sjpk else if (strstr(link, "fd") || strstr(link, "rfd") || 18211676Sjpk strstr(link, "diskette") || strstr(link, "rdiskette")) 18221676Sjpk flag = DA_FLOPPY; 18231676Sjpk else if (strstr(link, DA_TAPE_NAME)) 18241676Sjpk flag = DA_TAPE; 18251676Sjpk else 18261676Sjpk flag = DA_RMDISK; 18271676Sjpk 18281676Sjpk switch (type) { 18291676Sjpk case DA_AUDIO: 18301676Sjpk dentry = dlist->audio; 18311676Sjpk break; 18321676Sjpk case DA_CD: 18331676Sjpk dentry = dlist->cd; 18341676Sjpk break; 18351676Sjpk case DA_FLOPPY: 18361676Sjpk dentry = dlist->floppy; 18371676Sjpk break; 18381676Sjpk case DA_TAPE: 18391676Sjpk dentry = dlist->tape; 18401676Sjpk break; 18411676Sjpk case DA_RMDISK: 18421676Sjpk dentry = dlist->rmdisk; 18431676Sjpk break; 18441676Sjpk default: 18451676Sjpk return (-1); 18461676Sjpk } 18471676Sjpk 18481676Sjpk if ((type != NULL) && (link == NULL)) { 18491676Sjpk for (current = dentry, prev = dentry; current != NULL; 18501676Sjpk current = current->next) { 18511676Sjpk oldlist = strdup(current->devinfo.devlist); 18521676Sjpk for (lname = strtok_r(oldlist, " ", &lasts); 18531676Sjpk lname != NULL; 18541676Sjpk lname = strtok_r(NULL, " ", &lasts)) { 18551676Sjpk if (stat(lname, &rmstat) != 0) { 18561676Sjpk remove_dev = 1; 18571676Sjpk goto remove_dev; 18581676Sjpk } 18591676Sjpk } 18601676Sjpk prev = current; 18611676Sjpk } 18621676Sjpk return (-1); 18631676Sjpk } 18641676Sjpk 18651676Sjpk for (current = dentry, prev = dentry; current != NULL; 18661676Sjpk current = current->next) { 18671676Sjpk plen = strlen(current->devinfo.devlist); 18681676Sjpk nlen = strlen(link); 18691676Sjpk if (plen == nlen) { 18701676Sjpk if (strcmp(current->devinfo.devlist, link) == 0) { 18711676Sjpk /* last name in the list */ 18721676Sjpk remove_dev = 1; 18731676Sjpk break; 18741676Sjpk } 18751676Sjpk } 18761676Sjpk if (strstr(current->devinfo.devlist, link)) { 18771676Sjpk nlen = plen - nlen + 1; 18781676Sjpk oldlist = strdup(current->devinfo.devlist); 18791676Sjpk if ((current->devinfo.devlist = 18801676Sjpk (char *)realloc(current->devinfo.devlist, 18811676Sjpk nlen)) == NULL) { 18821676Sjpk free(oldlist); 18831676Sjpk return (-1); 18841676Sjpk } 18851676Sjpk current->devinfo.devlist[0] = '\0'; 18861676Sjpk nlen = plen = slen = 0; 18871676Sjpk for (lname = strtok_r(oldlist, " ", &lasts); 18881676Sjpk lname != NULL; 18891676Sjpk lname = strtok_r(NULL, " ", &lasts)) { 18901676Sjpk if (strcmp(lname, link) == 0) 18911676Sjpk continue; 18921676Sjpk nlen = strlen(lname) + plen + 1; 18931676Sjpk if (plen == 0) { 18941676Sjpk slen = 18951676Sjpk snprintf(current->devinfo.devlist, 18964514Saj nlen, "%s", lname); 18971676Sjpk } else { 18981676Sjpk slen = 18991676Sjpk snprintf(current->devinfo.devlist + 19004514Saj plen, nlen - plen, " %s", lname); 19011676Sjpk } 19021676Sjpk plen = plen + slen + 1; 19031676Sjpk } 19041676Sjpk free(oldlist); 19051676Sjpk break; 19061676Sjpk } 19071676Sjpk prev = current; 19081676Sjpk } 19091676Sjpk 19101676Sjpk remove_dev: 19111676Sjpk if (remove_dev == 1) { 19121676Sjpk (void) strlcpy(devname, current->devinfo.devname, size); 19131676Sjpk free(current->devinfo.devname); 19141676Sjpk free(current->devinfo.devlist); 19151676Sjpk current->devinfo.devname = current->devinfo.devlist = NULL; 19161676Sjpk prev->next = current->next; 19171676Sjpk free(current); 19181676Sjpk current = NULL; 19191676Sjpk } 19201676Sjpk if ((remove_dev == 1) && (prev->devinfo.devname == NULL)) { 19211676Sjpk if (prev->next) { 19221676Sjpk /* 19231676Sjpk * what we removed above was the first entry 19241676Sjpk * in the list. make the next entry to be the 19251676Sjpk * first. 19261676Sjpk */ 19271676Sjpk current = prev->next; 19281676Sjpk } else { 19291676Sjpk /* 19301676Sjpk * the matching entry was the only entry in the list 19311676Sjpk * for this type. 19321676Sjpk */ 19331676Sjpk current = NULL; 19341676Sjpk } 19351676Sjpk if (flag & DA_AUDIO) 19361676Sjpk dlist->audio = current; 19371676Sjpk else if (flag & DA_CD) 19381676Sjpk dlist->cd = current; 19391676Sjpk else if (flag & DA_FLOPPY) 19401676Sjpk dlist->floppy = current; 19411676Sjpk else if (flag & DA_TAPE) 19421676Sjpk dlist->tape = current; 19431676Sjpk else if (flag & DA_RMDISK) 19441676Sjpk dlist->rmdisk = current; 19451676Sjpk } 19461676Sjpk 19471676Sjpk return (flag); 19481676Sjpk } 19491676Sjpk 19501676Sjpk /* 1951*11529SJan.Parcel@Sun.COM * da_rm_list_entry - 1952*11529SJan.Parcel@Sun.COM * 1953*11529SJan.Parcel@Sun.COM * The adding of devnames to a devlist and the removal of a 1954*11529SJan.Parcel@Sun.COM * device are not symmetrical -- hot_cleanup gives a /devices 1955*11529SJan.Parcel@Sun.COM * name which is used to remove the dentry whose links all point to 1956*11529SJan.Parcel@Sun.COM * that /devices entry. 1957*11529SJan.Parcel@Sun.COM * 1958*11529SJan.Parcel@Sun.COM * The link argument is present if available to make debugging 1959*11529SJan.Parcel@Sun.COM * easier. 1960*11529SJan.Parcel@Sun.COM * 1961*11529SJan.Parcel@Sun.COM * da_rm_list_entry removes an entry from the linked list of devices. 1962*11529SJan.Parcel@Sun.COM * 1963*11529SJan.Parcel@Sun.COM * Returns 1 if the devname was removed successfully, 1964*11529SJan.Parcel@Sun.COM * 0 if not found, -1 for error. 1965*11529SJan.Parcel@Sun.COM */ 1966*11529SJan.Parcel@Sun.COM /*ARGSUSED*/ 1967*11529SJan.Parcel@Sun.COM int 1968*11529SJan.Parcel@Sun.COM da_rm_list_entry(devlist_t *dlist, char *link, int type, char *devname) 1969*11529SJan.Parcel@Sun.COM { 1970*11529SJan.Parcel@Sun.COM int retval = 0; 1971*11529SJan.Parcel@Sun.COM deventry_t **dentry, *current, *prev; 1972*11529SJan.Parcel@Sun.COM 1973*11529SJan.Parcel@Sun.COM switch (type) { 1974*11529SJan.Parcel@Sun.COM case DA_AUDIO: 1975*11529SJan.Parcel@Sun.COM dentry = &(dlist->audio); 1976*11529SJan.Parcel@Sun.COM break; 1977*11529SJan.Parcel@Sun.COM case DA_CD: 1978*11529SJan.Parcel@Sun.COM dentry = &(dlist->cd); 1979*11529SJan.Parcel@Sun.COM break; 1980*11529SJan.Parcel@Sun.COM case DA_FLOPPY: 1981*11529SJan.Parcel@Sun.COM dentry = &(dlist->floppy); 1982*11529SJan.Parcel@Sun.COM break; 1983*11529SJan.Parcel@Sun.COM case DA_TAPE: 1984*11529SJan.Parcel@Sun.COM dentry = &(dlist->tape); 1985*11529SJan.Parcel@Sun.COM break; 1986*11529SJan.Parcel@Sun.COM case DA_RMDISK: 1987*11529SJan.Parcel@Sun.COM dentry = &(dlist->rmdisk); 1988*11529SJan.Parcel@Sun.COM break; 1989*11529SJan.Parcel@Sun.COM default: 1990*11529SJan.Parcel@Sun.COM return (-1); 1991*11529SJan.Parcel@Sun.COM } 1992*11529SJan.Parcel@Sun.COM 1993*11529SJan.Parcel@Sun.COM /* Presumably in daemon mode, no need to remove entry, list is empty */ 1994*11529SJan.Parcel@Sun.COM if (*dentry == (deventry_t *)NULL) 1995*11529SJan.Parcel@Sun.COM return (0); 1996*11529SJan.Parcel@Sun.COM 1997*11529SJan.Parcel@Sun.COM prev = NULL; 1998*11529SJan.Parcel@Sun.COM for (current = *dentry; current != NULL; 1999*11529SJan.Parcel@Sun.COM prev = current, current = current->next) { 2000*11529SJan.Parcel@Sun.COM if (strcmp(devname, current->devinfo.devname)) 2001*11529SJan.Parcel@Sun.COM continue; 2002*11529SJan.Parcel@Sun.COM retval = 1; 2003*11529SJan.Parcel@Sun.COM break; 2004*11529SJan.Parcel@Sun.COM } 2005*11529SJan.Parcel@Sun.COM if (retval == 0) 2006*11529SJan.Parcel@Sun.COM return (0); 2007*11529SJan.Parcel@Sun.COM free(current->devinfo.devname); 2008*11529SJan.Parcel@Sun.COM if (current->devinfo.devlist != NULL) 2009*11529SJan.Parcel@Sun.COM free(current->devinfo.devlist); 2010*11529SJan.Parcel@Sun.COM if (current->devinfo.devopts != NULL) 2011*11529SJan.Parcel@Sun.COM free(current->devinfo.devopts); 2012*11529SJan.Parcel@Sun.COM 2013*11529SJan.Parcel@Sun.COM if (prev == NULL) 2014*11529SJan.Parcel@Sun.COM *dentry = current->next; 2015*11529SJan.Parcel@Sun.COM else 2016*11529SJan.Parcel@Sun.COM prev->next = current->next; 2017*11529SJan.Parcel@Sun.COM 2018*11529SJan.Parcel@Sun.COM free(current); 2019*11529SJan.Parcel@Sun.COM return (retval); 2020*11529SJan.Parcel@Sun.COM } 2021*11529SJan.Parcel@Sun.COM 2022*11529SJan.Parcel@Sun.COM /* 20231676Sjpk * da_is_on - 20241676Sjpk * checks if device allocation feature is turned on. 20251676Sjpk * returns 1 if on, 0 if off, -1 if status string not 20261676Sjpk * found in device_allocate. 20271676Sjpk */ 20281676Sjpk int 20291676Sjpk da_is_on() 20301676Sjpk { 20311676Sjpk return (getdaon()); 20321676Sjpk } 20331676Sjpk 20341676Sjpk /* 20351676Sjpk * da_print_device - 20361676Sjpk * debug routine to print device entries. 20371676Sjpk */ 20381676Sjpk void 20391676Sjpk da_print_device(int flag, devlist_t *devlist) 20401676Sjpk { 20411676Sjpk deventry_t *entry, *dentry; 20421676Sjpk devinfo_t *devinfo; 20431676Sjpk 20441676Sjpk if (flag & DA_AUDIO) 20451676Sjpk dentry = devlist->audio; 20461676Sjpk else if (flag & DA_CD) 20471676Sjpk dentry = devlist->cd; 20481676Sjpk else if (flag & DA_FLOPPY) 20491676Sjpk dentry = devlist->floppy; 20501676Sjpk else if (flag & DA_TAPE) 20511676Sjpk dentry = devlist->tape; 20521676Sjpk else if (flag & DA_RMDISK) 20531676Sjpk dentry = devlist->rmdisk; 20541676Sjpk else 20551676Sjpk return; 20561676Sjpk 20571676Sjpk for (entry = dentry; entry != NULL; entry = entry->next) { 20581676Sjpk devinfo = &(entry->devinfo); 20591676Sjpk (void) fprintf(stdout, "name: %s\n", devinfo->devname); 20601676Sjpk (void) fprintf(stdout, "type: %s\n", devinfo->devtype); 20611676Sjpk (void) fprintf(stdout, "auth: %s\n", devinfo->devauths); 20621676Sjpk (void) fprintf(stdout, "exec: %s\n", devinfo->devexec); 20631676Sjpk (void) fprintf(stdout, "list: %s\n\n", devinfo->devlist); 20641676Sjpk } 20651676Sjpk } 2066