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