xref: /illumos-gate/usr/src/lib/libadm/common/putdev.c (revision 4656d474)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright (c) 1996-1997, by Sun Microsystems, Inc.
247c478bd9Sstevel@tonic-gate  * All Rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
29*4656d474SGarrett D'Amore /*
30*4656d474SGarrett D'Amore  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
31*4656d474SGarrett D'Amore  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /* LINTLIBRARY */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * putdev.c
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  * Global Definitions:
397c478bd9Sstevel@tonic-gate  *	_adddevtabrec()		Add a record to the device table
407c478bd9Sstevel@tonic-gate  *	_putdevtabrec()		Write a record to the device table
417c478bd9Sstevel@tonic-gate  *	_moddevtabrec()		Modify a device-table record
427c478bd9Sstevel@tonic-gate  *	_rmdevtabrec()		Remove a device-table record
437c478bd9Sstevel@tonic-gate  *	_rmdevtabattrs()	Remove attributes from a device-table record
447c478bd9Sstevel@tonic-gate  *	oam_devtab		File descriptor of the open device table
457c478bd9Sstevel@tonic-gate  */
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate  *  G L O B A L   R E F E R E N C E S
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  *	Header Files
517c478bd9Sstevel@tonic-gate  *	Externals Referenced
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * Header Files
567c478bd9Sstevel@tonic-gate  *	<sys/types.h>		UNIX(r) Data Types
577c478bd9Sstevel@tonic-gate  *	<sys/stat.h>
587c478bd9Sstevel@tonic-gate  *	<stdio.h>		Standard I/O definitions
597c478bd9Sstevel@tonic-gate  *	<fcntl.h>		Definitions for file control
607c478bd9Sstevel@tonic-gate  *	<errno.h>		Error handling definitions
617c478bd9Sstevel@tonic-gate  *	<string.h>		String Handling Definitions
627c478bd9Sstevel@tonic-gate  *	<devmgmt.h>		Device Management Definitions
637c478bd9Sstevel@tonic-gate  *	<unistd.h>		Get UNIX(r) Standard Definitions
647c478bd9Sstevel@tonic-gate  *	"devtab.h"		Local Device Management Definitions
657c478bd9Sstevel@tonic-gate  */
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #include	<sys/types.h>
687c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
697c478bd9Sstevel@tonic-gate #include	<stdio.h>
707c478bd9Sstevel@tonic-gate #include	<fcntl.h>
717c478bd9Sstevel@tonic-gate #include	<errno.h>
727c478bd9Sstevel@tonic-gate #include	<string.h>
737c478bd9Sstevel@tonic-gate #include	<devmgmt.h>
747c478bd9Sstevel@tonic-gate #include	<unistd.h>
757c478bd9Sstevel@tonic-gate #include	<stdlib.h>
767c478bd9Sstevel@tonic-gate #include	"devtab.h"
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate  *  L O C A L   D E F I N I T I O N S
807c478bd9Sstevel@tonic-gate  *
817c478bd9Sstevel@tonic-gate  *	TDTABNM		Name of the temporary device table (in the
827c478bd9Sstevel@tonic-gate  *			directory of the existing table)
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate #define	TDTABNM		"%sdevtab.%6.6d"
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * Static functions
907c478bd9Sstevel@tonic-gate  *	strcatesc	Copies a character-string from one place to another
917c478bd9Sstevel@tonic-gate  *			escaping the appropriate characters
927c478bd9Sstevel@tonic-gate  *	lkdevtab	Locks the device table
937c478bd9Sstevel@tonic-gate  *	unlkdevtab	Unlocks the device table
947c478bd9Sstevel@tonic-gate  *	mkdevtabent	Builds a device-table entry from the alias and the
957c478bd9Sstevel@tonic-gate  *			list of attr=val pairs given
967c478bd9Sstevel@tonic-gate  *	opennewdevtab	Opens a new device table (as a temp file)
977c478bd9Sstevel@tonic-gate  *	mknewdevtab	Makes the temp device table the new devtab
987c478bd9Sstevel@tonic-gate  *	rmnewdevtab	Remove the temporary device table and free space
997c478bd9Sstevel@tonic-gate  *			allocated to the filename of that file.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate static	char			*strcatesc(char *, char *);
1037c478bd9Sstevel@tonic-gate static	int			lkdevtab(char *, short);
1047c478bd9Sstevel@tonic-gate static	int			unlkdevtab(void);
1057c478bd9Sstevel@tonic-gate static	struct devtabent	*mkdevtabent(char *, char **);
1067c478bd9Sstevel@tonic-gate static	FILE			*opennewdevtab(char **);
1077c478bd9Sstevel@tonic-gate static	int			mknewdevtab(char *);
1087c478bd9Sstevel@tonic-gate static	int			rmnewdevtab(char *);
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate /*
1117c478bd9Sstevel@tonic-gate  * char *strcatesc(p, q)
1127c478bd9Sstevel@tonic-gate  *	char   *p
1137c478bd9Sstevel@tonic-gate  *	char   *q
1147c478bd9Sstevel@tonic-gate  *
1157c478bd9Sstevel@tonic-gate  *	Write the character-string pointed to by "q" to the place
1167c478bd9Sstevel@tonic-gate  *	pointed to by "p", escaping those characters in "q" found in the
1177c478bd9Sstevel@tonic-gate  *	string "DTAB_ESCS" by preceding them with '\\'.  Return a pointer to
1187c478bd9Sstevel@tonic-gate  *	the byte beyond the last character written to "p".
1197c478bd9Sstevel@tonic-gate  *
1207c478bd9Sstevel@tonic-gate  *  Arguments:
1217c478bd9Sstevel@tonic-gate  *	p		The place to begin writing to
1227c478bd9Sstevel@tonic-gate  *	q		The string to write
1237c478bd9Sstevel@tonic-gate  *
1247c478bd9Sstevel@tonic-gate  *  Returns:  char *
1257c478bd9Sstevel@tonic-gate  *	The address of the byte beyond the last character written into "p"
1267c478bd9Sstevel@tonic-gate  */
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate static char *
strcatesc(char * p,char * q)1297c478bd9Sstevel@tonic-gate strcatesc(
1307c478bd9Sstevel@tonic-gate 	char   *p,		/* Place to write to */
1317c478bd9Sstevel@tonic-gate 	char   *q)		/* Thing to write */
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	while (*q) {
1347c478bd9Sstevel@tonic-gate 	    if (strchr(DTAB_ESCS, *q)) *p++ = '\\';
1357c478bd9Sstevel@tonic-gate 	    *p++ = *q++;
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate 	return (p);
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate  * FILE *opennewdevtab(pname)
1427c478bd9Sstevel@tonic-gate  *	char   **pname
1437c478bd9Sstevel@tonic-gate  *
1447c478bd9Sstevel@tonic-gate  *	Generates a temporary device-table name from the existing
1457c478bd9Sstevel@tonic-gate  *	device table name (in the same directory) and opens that
1467c478bd9Sstevel@tonic-gate  *	file for writing.  It puts a pointer to the malloc()ed space
1477c478bd9Sstevel@tonic-gate  *	containing the temp device table's name at the place referenced
1487c478bd9Sstevel@tonic-gate  *	by <pname>.
1497c478bd9Sstevel@tonic-gate  *
1507c478bd9Sstevel@tonic-gate  *  Arguments:
1517c478bd9Sstevel@tonic-gate  *	pname	Pointer to the char * to contain the address of the name
1527c478bd9Sstevel@tonic-gate  *		of the temporary file
1537c478bd9Sstevel@tonic-gate  *
1547c478bd9Sstevel@tonic-gate  *  Returns:  FILE *
1557c478bd9Sstevel@tonic-gate  *	A pointer to the opened stream or (FILE *) NULL if an error occurred.
1567c478bd9Sstevel@tonic-gate  *	If an error occurred, "errno" will be set to reflect the problem.
1577c478bd9Sstevel@tonic-gate  */
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate static FILE *
opennewdevtab(char ** pname)1607c478bd9Sstevel@tonic-gate opennewdevtab(char  **pname)		/* A(ptr to temp filename's path) */
1617c478bd9Sstevel@tonic-gate {
1627c478bd9Sstevel@tonic-gate 	char   *oldname;		/* Ptr to the device-table's name */
1637c478bd9Sstevel@tonic-gate 	char   *buf;			/* Ptr to the temp file's name */
1647c478bd9Sstevel@tonic-gate 	char   *dirname;		/* Directory containing devtab */
1657c478bd9Sstevel@tonic-gate 	char   *p;			/* Ptr to last '/' in devtab name */
1667c478bd9Sstevel@tonic-gate 	int    fd;			/* Opened file descriptor */
1677c478bd9Sstevel@tonic-gate 	FILE   *fp;			/* Opened file pointer */
1687c478bd9Sstevel@tonic-gate 	struct stat64	sbuf;		/* stat buf for old devtab file */
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	fp = NULL;
1717c478bd9Sstevel@tonic-gate 	if (oldname = _devtabpath()) {
1727c478bd9Sstevel@tonic-gate 	/*
1737c478bd9Sstevel@tonic-gate 	 * It is possible for us to have sufficient permissions to create
1747c478bd9Sstevel@tonic-gate 	 * the new file without having sufficient permissions to write the
1757c478bd9Sstevel@tonic-gate 	 * original devtab file.  For consistency with the operations which
1767c478bd9Sstevel@tonic-gate 	 * modify the original file by writing it directly we require write
1777c478bd9Sstevel@tonic-gate 	 * permissions for the original file in order to make a new one.
1787c478bd9Sstevel@tonic-gate 	 */
1797c478bd9Sstevel@tonic-gate 	    if ((fd = open(oldname, O_WRONLY)) == -1)
1807c478bd9Sstevel@tonic-gate 		return (NULL);
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	    if (fstat64(fd, &sbuf) == -1) {
1837c478bd9Sstevel@tonic-gate 		(void) close(fd);
1847c478bd9Sstevel@tonic-gate 		return (NULL);
1857c478bd9Sstevel@tonic-gate 	    }
1867c478bd9Sstevel@tonic-gate 	    (void) close(fd);
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	    if (p = strrchr(oldname, '/')) {
1897c478bd9Sstevel@tonic-gate 		*(p+1) = '\0';
1907c478bd9Sstevel@tonic-gate 		dirname = oldname;
1917c478bd9Sstevel@tonic-gate 	    } else dirname = "./";
192*4656d474SGarrett D'Amore 	    if (asprintf(&buf, TDTABNM, dirname, getpid()) >= 0) {
1937c478bd9Sstevel@tonic-gate 
194*4656d474SGarrett D'Amore 		    /*
195*4656d474SGarrett D'Amore 		     * Build the name of the temp device table and
196*4656d474SGarrett D'Amore 		     * open the file.  We must reset the owner, group
197*4656d474SGarrett D'Amore 		     * and perms to those of the original devtab file.
198*4656d474SGarrett D'Amore 		     */
199*4656d474SGarrett D'Amore 		    if (fp = fopen(buf, "w")) {
200*4656d474SGarrett D'Amore 			    *pname = buf;
201*4656d474SGarrett D'Amore 			    (void) fchmod(fileno(fp), sbuf.st_mode & 0777);
202*4656d474SGarrett D'Amore 			    (void) fchown(fileno(fp), sbuf.st_uid, sbuf.st_gid);
203*4656d474SGarrett D'Amore 		    } else {
204*4656d474SGarrett D'Amore 			    free(buf);
205*4656d474SGarrett D'Amore 		    }
2067c478bd9Sstevel@tonic-gate 	    }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	/*
2097c478bd9Sstevel@tonic-gate 	 *
2107c478bd9Sstevel@tonic-gate 	 * Free the space containing the device table's name.
2117c478bd9Sstevel@tonic-gate 	 */
2127c478bd9Sstevel@tonic-gate 	    free(oldname);
2137c478bd9Sstevel@tonic-gate 	}
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	/* Finished.  Return what we've got */
2167c478bd9Sstevel@tonic-gate 	return (fp);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate  *  int rmnewdevtab(tempname)
2217c478bd9Sstevel@tonic-gate  *	char   *tempname
2227c478bd9Sstevel@tonic-gate  *
2237c478bd9Sstevel@tonic-gate  *	Unlink the temp device table and free the memory allocated to
2247c478bd9Sstevel@tonic-gate  *	contain the name of that file
2257c478bd9Sstevel@tonic-gate  *
2267c478bd9Sstevel@tonic-gate  *  Arguments:
2277c478bd9Sstevel@tonic-gate  *	tempname	Name of the temporary file
2287c478bd9Sstevel@tonic-gate  *
2297c478bd9Sstevel@tonic-gate  *  Returns: int
2307c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise
2317c478bd9Sstevel@tonic-gate  */
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate static int
rmnewdevtab(char * tempname)2347c478bd9Sstevel@tonic-gate rmnewdevtab(char *tempname)	/* Filename of new device table */
2357c478bd9Sstevel@tonic-gate {
2367c478bd9Sstevel@tonic-gate 	int	noerr;		/* Flag, TRUE if no error, FALSE otherwise */
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	/* Unlink the file */
2397c478bd9Sstevel@tonic-gate 	noerr = (unlink(tempname) == 0);
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	/* Free the space allocated to the filename */
2427c478bd9Sstevel@tonic-gate 	free(tempname);
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	/* Return success indicator */
2457c478bd9Sstevel@tonic-gate 	return (noerr);
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate  *  int mknewdevtab(tempname)
2507c478bd9Sstevel@tonic-gate  *	char   *tempname
2517c478bd9Sstevel@tonic-gate  *
2527c478bd9Sstevel@tonic-gate  *	Make the temporary device-table the new system device table
2537c478bd9Sstevel@tonic-gate  *
2547c478bd9Sstevel@tonic-gate  *  Arguments:
2557c478bd9Sstevel@tonic-gate  *	tempname	Name of the temporary file
2567c478bd9Sstevel@tonic-gate  *
2577c478bd9Sstevel@tonic-gate  *  Returns:  int
2587c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise
2597c478bd9Sstevel@tonic-gate  *
2607c478bd9Sstevel@tonic-gate  *  Notes:
2617c478bd9Sstevel@tonic-gate  *	- Need to use rename() someday instead of link()/unlink()
2627c478bd9Sstevel@tonic-gate  *	- This code is somewhat ineffecient in that asks for the name
2637c478bd9Sstevel@tonic-gate  *	  of the device-table more than once.  Done so that we don't
2647c478bd9Sstevel@tonic-gate  *	  have to manage that space, but this may be somewhat lazy.
2657c478bd9Sstevel@tonic-gate  */
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate static int
mknewdevtab(char * tempname)2687c478bd9Sstevel@tonic-gate mknewdevtab(char   *tempname)		/* Ptr to name of temp dev tab */
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate 	char   *devtabname;		/* Ptr to the device table's name */
2717c478bd9Sstevel@tonic-gate 	int	noerr;			/* FLAG, TRUE if all's well */
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	/* Get the device table's pathname */
2747c478bd9Sstevel@tonic-gate 	if (devtabname = _devtabpath()) {
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	    /* Unlink the existing file */
2777c478bd9Sstevel@tonic-gate 	    if (unlink(devtabname) == 0) {
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 		/* Make the temp file the real device table */
2807c478bd9Sstevel@tonic-gate 		noerr = (link(tempname, devtabname) == 0) ? TRUE : FALSE;
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 		/* Remove the temp file (and resources) */
2837c478bd9Sstevel@tonic-gate 		if (noerr) (void) rmnewdevtab(tempname);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;	/* unlink() failed */
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	    /* Free the device table's name */
2887c478bd9Sstevel@tonic-gate 	    free(devtabname);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	} else noerr = FALSE; 	/* devtabpath() failed */
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	/* Finished.  Return success indicator */
2937c478bd9Sstevel@tonic-gate 	return (noerr);
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate /*
2977c478bd9Sstevel@tonic-gate  * static int lkdevtab(o_mode, lktype)
2987c478bd9Sstevel@tonic-gate  *	char   *o_mode
2997c478bd9Sstevel@tonic-gate  *	short	lktype
3007c478bd9Sstevel@tonic-gate  *
3017c478bd9Sstevel@tonic-gate  *	Lock the device table for writing.  If it isn't available, it waits
3027c478bd9Sstevel@tonic-gate  *	until it is.
3037c478bd9Sstevel@tonic-gate  *
3047c478bd9Sstevel@tonic-gate  *  Arguments:
3057c478bd9Sstevel@tonic-gate  *	o_mode	The open() mode to use when opening the device table
3067c478bd9Sstevel@tonic-gate  *	lktype	The type of lock to apply
3077c478bd9Sstevel@tonic-gate  *
3087c478bd9Sstevel@tonic-gate  *  Returns:  int
3097c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE with errno set otherwise
3107c478bd9Sstevel@tonic-gate  */
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate static int
lkdevtab(char * o_mode,short lktype)3137c478bd9Sstevel@tonic-gate lkdevtab(
3147c478bd9Sstevel@tonic-gate 	char   *o_mode,				/* Open mode */
3157c478bd9Sstevel@tonic-gate 	short	lktype)				/* Lock type */
3167c478bd9Sstevel@tonic-gate {
3177c478bd9Sstevel@tonic-gate 	/* Automatic data */
3187c478bd9Sstevel@tonic-gate 	struct flock	lockinfo;		/* File locking structure */
3197c478bd9Sstevel@tonic-gate 	int		noerr;			/* FLAG, TRUE if no error */
3207c478bd9Sstevel@tonic-gate 	int		olderrno;		/* Old value of "errno" */
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	/* Close the device table (if it's open) */
3247c478bd9Sstevel@tonic-gate 	_enddevtab();
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	/* Open the device table for read/append */
3277c478bd9Sstevel@tonic-gate 	noerr = TRUE;
3287c478bd9Sstevel@tonic-gate 	if (_opendevtab(o_mode)) {
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	/*
3317c478bd9Sstevel@tonic-gate 	 * Lock the device table (for writing).  If it's not
3327c478bd9Sstevel@tonic-gate 	 * available, wait until it is, then close and open the
3337c478bd9Sstevel@tonic-gate 	 * table (modify and delete change the table!) and try
3347c478bd9Sstevel@tonic-gate 	 * to lock it again
3357c478bd9Sstevel@tonic-gate 	 */
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	    /* Build the locking structure */
3387c478bd9Sstevel@tonic-gate 	    lockinfo.l_type = lktype;
3397c478bd9Sstevel@tonic-gate 	    lockinfo.l_whence = 0;
3407c478bd9Sstevel@tonic-gate 	    lockinfo.l_start = 0L;
3417c478bd9Sstevel@tonic-gate 	    lockinfo.l_len = 0L;
3427c478bd9Sstevel@tonic-gate 	    olderrno = errno;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	    /* Keep on going until we lock the file or an error happens */
3457c478bd9Sstevel@tonic-gate 	    while ((fcntl(fileno(oam_devtab), F_SETLK, &lockinfo) == -1) &&
3467c478bd9Sstevel@tonic-gate 		!noerr) {
3477c478bd9Sstevel@tonic-gate 		if (errno == EACCES) {
3487c478bd9Sstevel@tonic-gate 		    if (fcntl(fileno(oam_devtab), F_SETLKW, &lockinfo) == -1)
3497c478bd9Sstevel@tonic-gate 			noerr = FALSE;
3507c478bd9Sstevel@tonic-gate 		    else {
3517c478bd9Sstevel@tonic-gate 			/* Reopen the file (maybe it's moved?) */
3527c478bd9Sstevel@tonic-gate 			_enddevtab();
3537c478bd9Sstevel@tonic-gate 			if (!_opendevtab(o_mode)) noerr = FALSE;
3547c478bd9Sstevel@tonic-gate 			else errno = olderrno;
3557c478bd9Sstevel@tonic-gate 		    }
3567c478bd9Sstevel@tonic-gate 		} else noerr = FALSE;
3577c478bd9Sstevel@tonic-gate 	    }
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	    if (!noerr) _enddevtab();  /* Don't keep open if in error */
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	/* Done */
3647c478bd9Sstevel@tonic-gate 	return (noerr);
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate /*
3687c478bd9Sstevel@tonic-gate  * int unlkdevtab()
3697c478bd9Sstevel@tonic-gate  *
3707c478bd9Sstevel@tonic-gate  *	Unlock the locked device table.
3717c478bd9Sstevel@tonic-gate  *
3727c478bd9Sstevel@tonic-gate  *  Arguments:  None
3737c478bd9Sstevel@tonic-gate  *
3747c478bd9Sstevel@tonic-gate  *  Returns:  int
3757c478bd9Sstevel@tonic-gate  *	Whatever fcntl() returns...
3767c478bd9Sstevel@tonic-gate  */
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate static int
unlkdevtab(void)3797c478bd9Sstevel@tonic-gate unlkdevtab(void)
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate 	/* Automatic data */
3827c478bd9Sstevel@tonic-gate 	struct flock	lockinfo;		/* Locking structure */
3837c478bd9Sstevel@tonic-gate 	int		noerr;			/* FLAG, TRUE if all's well */
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	/* Build the locking structure */
3867c478bd9Sstevel@tonic-gate 	lockinfo.l_type = F_UNLCK;		/* Lock type */
3877c478bd9Sstevel@tonic-gate 	lockinfo.l_whence = 0;			/* Count from top of file */
3887c478bd9Sstevel@tonic-gate 	lockinfo.l_start = 0L;			/* From beginning */
3897c478bd9Sstevel@tonic-gate 	lockinfo.l_len = 0L;			/* Length of locked data */
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	/* Unlock it */
3927c478bd9Sstevel@tonic-gate 	noerr = (fcntl(fileno(oam_devtab), F_SETLK, &lockinfo) != -1);
3937c478bd9Sstevel@tonic-gate 	_enddevtab();
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	/* Finished */
3967c478bd9Sstevel@tonic-gate 	return (noerr);
3977c478bd9Sstevel@tonic-gate }
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate /*
4007c478bd9Sstevel@tonic-gate  * struct devtabent *mkdevtabent(alias, attrlist)
4017c478bd9Sstevel@tonic-gate  *	char   *alias
4027c478bd9Sstevel@tonic-gate  *	char  **attrlist
4037c478bd9Sstevel@tonic-gate  *
4047c478bd9Sstevel@tonic-gate  *	This function builds a struct devtabent structure describing the
4057c478bd9Sstevel@tonic-gate  *	alias <alias> using the information in the attribute list <attrlist>.
4067c478bd9Sstevel@tonic-gate  *	The <attrlist> contains data of the form attr=value where attr is
4077c478bd9Sstevel@tonic-gate  *	the name of an attribute and value is the value of that attribute.
4087c478bd9Sstevel@tonic-gate  *
4097c478bd9Sstevel@tonic-gate  *  Arguments:
4107c478bd9Sstevel@tonic-gate  *	alias		The alias being added to the device table
4117c478bd9Sstevel@tonic-gate  *	attrlist	The attributes and values for that alias
4127c478bd9Sstevel@tonic-gate  *
4137c478bd9Sstevel@tonic-gate  *  Returns:  struct devtabent *
4147c478bd9Sstevel@tonic-gate  *	A completed struct devtabent structure containing the description
4157c478bd9Sstevel@tonic-gate  *	of the alias.  The structure, and all of the data in the structure
4167c478bd9Sstevel@tonic-gate  *	are each in space allocated using the malloc() function and should
4177c478bd9Sstevel@tonic-gate  *	be freed using the free() function (or the _freedevtabent() function).
4187c478bd9Sstevel@tonic-gate  *
4197c478bd9Sstevel@tonic-gate  *  Errors:
4207c478bd9Sstevel@tonic-gate  *	EINVAL	If "alias" is used as an attribute in an attr=val pair
4217c478bd9Sstevel@tonic-gate  *	EAGAIN	If an attribute is specified more than once
4227c478bd9Sstevel@tonic-gate  */
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate static struct devtabent *
mkdevtabent(char * alias,char ** attrlist)4257c478bd9Sstevel@tonic-gate mkdevtabent(
4267c478bd9Sstevel@tonic-gate 	char   *alias,		/* Alias of entry */
4277c478bd9Sstevel@tonic-gate 	char  **attrlist)	/* Attributes of new entry */
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	/* Automatic data */
4307c478bd9Sstevel@tonic-gate 	struct devtabent	*devtabent;	/* * to struct we're making */
4317c478bd9Sstevel@tonic-gate 	struct attrval		*prevattrval;	/* * to prev attr/val struct */
4327c478bd9Sstevel@tonic-gate 	struct attrval		*attrval;	/* * to current struct */
4337c478bd9Sstevel@tonic-gate 	char			**pp;		/* Ptr into list of ptrs */
4347c478bd9Sstevel@tonic-gate 	char			*peq;		/* Ptr to '=' in string */
4357c478bd9Sstevel@tonic-gate 	char			*val;		/* Ptr to space for value */
4367c478bd9Sstevel@tonic-gate 	char			*name;		/* Ptr to space for name */
4377c478bd9Sstevel@tonic-gate 	ssize_t			len;		/* Length of name */
4387c478bd9Sstevel@tonic-gate 	int			noerr;		/* TRUE if all's well */
4397c478bd9Sstevel@tonic-gate 	int			found;		/* TRUE the attr is found */
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	/* No problems (yet) */
4437c478bd9Sstevel@tonic-gate 	noerr = TRUE;
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	/* Get space for the structure */
4467c478bd9Sstevel@tonic-gate 	if (devtabent = malloc(sizeof (struct devtabent))) {
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	    /* Fill in default values */
4497c478bd9Sstevel@tonic-gate 	    if (devtabent->alias = malloc(strlen(alias)+1)) {
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 		(void) strcpy(devtabent->alias, alias);		/* alias */
4527c478bd9Sstevel@tonic-gate 		devtabent->comment = FALSE;			/* data rec */
4537c478bd9Sstevel@tonic-gate 		devtabent->cdevice = NULL;			/* cdevice */
4547c478bd9Sstevel@tonic-gate 		devtabent->bdevice = NULL;			/* bdevice */
4557c478bd9Sstevel@tonic-gate 		devtabent->pathname = NULL;			/* pathname */
4567c478bd9Sstevel@tonic-gate 		devtabent->attrstr = NULL;			/* string */
4577c478bd9Sstevel@tonic-gate 		devtabent->attrlist = NULL;			/* attr list */
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 		/* Add attributes to the structure */
4607c478bd9Sstevel@tonic-gate 		prevattrval = NULL;
4617c478bd9Sstevel@tonic-gate 		if ((pp = attrlist) != NULL)
4627c478bd9Sstevel@tonic-gate 		    while (*pp && noerr) {
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		    /* Valid attr=value pair? */
4657c478bd9Sstevel@tonic-gate 		    if (((peq = strchr(*pp, '=')) != NULL) &&
4667c478bd9Sstevel@tonic-gate 			((len = peq - *pp) > 0)) {
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 			/* Get space for the value */
4697c478bd9Sstevel@tonic-gate 			if (val = malloc(strlen(peq))) {
4707c478bd9Sstevel@tonic-gate 			    (void) strcpy(val, peq+1);		/* Copy it */
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 			    /* Get space for attribute name */
4737c478bd9Sstevel@tonic-gate 			    if (name = malloc((size_t)(len + 1))) {
4747c478bd9Sstevel@tonic-gate 				(void) strncpy(name, *pp, (size_t)len);
4757c478bd9Sstevel@tonic-gate 				*(name+len) = '\0';
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 				/* Specifying the alias?  If so, ERROR */
4787c478bd9Sstevel@tonic-gate 				if (strcmp(name, DTAB_ALIAS) == 0) {
4797c478bd9Sstevel@tonic-gate 				    noerr = FALSE;
4807c478bd9Sstevel@tonic-gate 				    free(name);
4817c478bd9Sstevel@tonic-gate 				    free(val);
4827c478bd9Sstevel@tonic-gate 				    errno = EINVAL;
4837c478bd9Sstevel@tonic-gate 				}
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 				/* Specifying the char device path? */
4867c478bd9Sstevel@tonic-gate 				else if (strcmp(name, DTAB_CDEVICE) == 0) {
4877c478bd9Sstevel@tonic-gate 				    if (!devtabent->cdevice) {
4887c478bd9Sstevel@tonic-gate 					if (val[0] != '/') {
4897c478bd9Sstevel@tonic-gate 						noerr = FALSE;
4907c478bd9Sstevel@tonic-gate 						free(name);
4917c478bd9Sstevel@tonic-gate 						free(val);
4927c478bd9Sstevel@tonic-gate 						errno = ENXIO;
4937c478bd9Sstevel@tonic-gate 					} else {
4947c478bd9Sstevel@tonic-gate 						devtabent->cdevice = val;
4957c478bd9Sstevel@tonic-gate 						free(name);
4967c478bd9Sstevel@tonic-gate 					}
4977c478bd9Sstevel@tonic-gate 				    } else {
4987c478bd9Sstevel@tonic-gate 					noerr = FALSE;
4997c478bd9Sstevel@tonic-gate 					free(name);
5007c478bd9Sstevel@tonic-gate 					free(val);
5017c478bd9Sstevel@tonic-gate 					errno = EAGAIN;
5027c478bd9Sstevel@tonic-gate 				    }
5037c478bd9Sstevel@tonic-gate 				}
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 				/* Specifying the block device path? */
5067c478bd9Sstevel@tonic-gate 				else if (strcmp(name, DTAB_BDEVICE) == 0) {
5077c478bd9Sstevel@tonic-gate 				    if (!devtabent->bdevice) {
5087c478bd9Sstevel@tonic-gate 					if (val[0] != '/') {
5097c478bd9Sstevel@tonic-gate 						noerr = FALSE;
5107c478bd9Sstevel@tonic-gate 						free(name);
5117c478bd9Sstevel@tonic-gate 						free(val);
5127c478bd9Sstevel@tonic-gate 						errno = ENXIO;
5137c478bd9Sstevel@tonic-gate 					} else {
5147c478bd9Sstevel@tonic-gate 						devtabent->bdevice = val;
5157c478bd9Sstevel@tonic-gate 						free(name);
5167c478bd9Sstevel@tonic-gate 					}
5177c478bd9Sstevel@tonic-gate 				    } else {
5187c478bd9Sstevel@tonic-gate 					noerr = FALSE;
5197c478bd9Sstevel@tonic-gate 					free(name);
5207c478bd9Sstevel@tonic-gate 					free(val);
5217c478bd9Sstevel@tonic-gate 					errno = EAGAIN;
5227c478bd9Sstevel@tonic-gate 				    }
5237c478bd9Sstevel@tonic-gate 				}
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 				/* Specifying the pathname (generic)? */
5267c478bd9Sstevel@tonic-gate 				else if (strcmp(name, DTAB_PATHNAME) == 0) {
5277c478bd9Sstevel@tonic-gate 				    if (!devtabent->pathname) {
5287c478bd9Sstevel@tonic-gate 					if (val[0] != '/') {
5297c478bd9Sstevel@tonic-gate 						noerr = FALSE;
5307c478bd9Sstevel@tonic-gate 						free(name);
5317c478bd9Sstevel@tonic-gate 						free(val);
5327c478bd9Sstevel@tonic-gate 						errno = ENXIO;
5337c478bd9Sstevel@tonic-gate 					} else {
5347c478bd9Sstevel@tonic-gate 						devtabent->pathname = val;
5357c478bd9Sstevel@tonic-gate 						free(name);
5367c478bd9Sstevel@tonic-gate 					}
5377c478bd9Sstevel@tonic-gate 				    } else {
5387c478bd9Sstevel@tonic-gate 					noerr = FALSE;
5397c478bd9Sstevel@tonic-gate 					free(name);
5407c478bd9Sstevel@tonic-gate 					free(val);
5417c478bd9Sstevel@tonic-gate 					errno = EAGAIN;
5427c478bd9Sstevel@tonic-gate 				    }
5437c478bd9Sstevel@tonic-gate 				}
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 				/* Some other attribute */
5467c478bd9Sstevel@tonic-gate 				else {
5477c478bd9Sstevel@tonic-gate 				    found = FALSE;
5487c478bd9Sstevel@tonic-gate 				    if ((attrval = devtabent->attrlist) != NULL)
5497c478bd9Sstevel@tonic-gate 					do {
5507c478bd9Sstevel@tonic-gate 					    if (strcmp(attrval->attr,
5517c478bd9Sstevel@tonic-gate 						name) == 0) {
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 						noerr = FALSE;
5547c478bd9Sstevel@tonic-gate 						free(name);
5557c478bd9Sstevel@tonic-gate 						free(val);
5567c478bd9Sstevel@tonic-gate 						errno = EAGAIN;
5577c478bd9Sstevel@tonic-gate 					    }
5587c478bd9Sstevel@tonic-gate 					} while (!found && noerr &&
5597c478bd9Sstevel@tonic-gate 					    (attrval = attrval->next));
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 				    if (!found && noerr) {
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 					/* Get space for attr/val structure */
5647c478bd9Sstevel@tonic-gate 					if (attrval =
5657c478bd9Sstevel@tonic-gate 					    malloc(sizeof (struct attrval))) {
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 					    /* Fill attr/val structure */
5687c478bd9Sstevel@tonic-gate 					    attrval->attr = name;
5697c478bd9Sstevel@tonic-gate 					    attrval->val = val;
5707c478bd9Sstevel@tonic-gate 					    attrval->next = NULL;
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 					/*
5737c478bd9Sstevel@tonic-gate 					 * Link into the list of attributes
5747c478bd9Sstevel@tonic-gate 					 */
5757c478bd9Sstevel@tonic-gate 					    if (prevattrval)
5767c478bd9Sstevel@tonic-gate 						prevattrval->next = attrval;
5777c478bd9Sstevel@tonic-gate 					    else devtabent->attrlist = attrval;
5787c478bd9Sstevel@tonic-gate 					    prevattrval = attrval;
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 					} else {
5817c478bd9Sstevel@tonic-gate 					    /* malloc() for attrval failed */
5827c478bd9Sstevel@tonic-gate 					    noerr = FALSE;
5837c478bd9Sstevel@tonic-gate 					    free(name);
5847c478bd9Sstevel@tonic-gate 					    free(val);
5857c478bd9Sstevel@tonic-gate 					}
5867c478bd9Sstevel@tonic-gate 				    }
5877c478bd9Sstevel@tonic-gate 				}   /* End else (some other attribute) */
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 			    } else { 	/* malloc() for attribute name failed */
5907c478bd9Sstevel@tonic-gate 				noerr = FALSE;
5917c478bd9Sstevel@tonic-gate 				free(val);
5927c478bd9Sstevel@tonic-gate 			    }
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 			} else noerr = FALSE;	/* Malloc() for "val" failed */
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 			/* If we saw an error, free structure, returning NULL */
5977c478bd9Sstevel@tonic-gate 			if (!noerr) {
5987c478bd9Sstevel@tonic-gate 			    _freedevtabent(devtabent);
5997c478bd9Sstevel@tonic-gate 			    devtabent = NULL;
6007c478bd9Sstevel@tonic-gate 			}
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 		    } 	/* Ignore invalid attr=val pair */
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 		    if (noerr) pp++;
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 		}   /* End attribute processing loop */
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	    } else {	/* malloc() failed */
6097c478bd9Sstevel@tonic-gate 		free(devtabent);
6107c478bd9Sstevel@tonic-gate 		devtabent = NULL;
6117c478bd9Sstevel@tonic-gate 	    }
6127c478bd9Sstevel@tonic-gate 	}
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	/* Finished */
6157c478bd9Sstevel@tonic-gate 	return (devtabent);
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate /*
6197c478bd9Sstevel@tonic-gate  * int _putdevtabrec(stream, rec)
6207c478bd9Sstevel@tonic-gate  *	FILE		       *stream
6217c478bd9Sstevel@tonic-gate  *	struct devtabent       *rec
6227c478bd9Sstevel@tonic-gate  *
6237c478bd9Sstevel@tonic-gate  *	Write a device table record containing the information in the struct
6247c478bd9Sstevel@tonic-gate  *	devtab structure <rec> to the current position of the standard I/O
6257c478bd9Sstevel@tonic-gate  *	stream <stream>.
6267c478bd9Sstevel@tonic-gate  *
6277c478bd9Sstevel@tonic-gate  *  Arguments:
6287c478bd9Sstevel@tonic-gate  *	stream		The stream to write to
6297c478bd9Sstevel@tonic-gate  *	rec		The structure containing the information to write
6307c478bd9Sstevel@tonic-gate  *
6317c478bd9Sstevel@tonic-gate  *  Returns:  int
6327c478bd9Sstevel@tonic-gate  *	The number of characters written or EOF if there was some error.
6337c478bd9Sstevel@tonic-gate  */
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate int
_putdevtabrec(FILE * stream,struct devtabent * rec)6367c478bd9Sstevel@tonic-gate _putdevtabrec(
6377c478bd9Sstevel@tonic-gate 	FILE			*stream,	/* Stream to which to write */
6387c478bd9Sstevel@tonic-gate 	struct devtabent	*rec)		/* Record to write */
6397c478bd9Sstevel@tonic-gate {
6407c478bd9Sstevel@tonic-gate 	/* Automatic Data */
6417c478bd9Sstevel@tonic-gate 	struct attrval		*attrval;	/* Ptr to attr/val pair */
6427c478bd9Sstevel@tonic-gate 	char			*buf;		/* Allocated buffer */
6437c478bd9Sstevel@tonic-gate 	char			*p;		/* Temp char pointer */
6447c478bd9Sstevel@tonic-gate 	int			count;		/* Number of chars written */
6457c478bd9Sstevel@tonic-gate 	size_t			size = 0;	/* Size of needed buffer */
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 	/* Comment or data record? */
6497c478bd9Sstevel@tonic-gate 	if (rec->comment) {
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	/*
6527c478bd9Sstevel@tonic-gate 	 * Record is a comment
6537c478bd9Sstevel@tonic-gate 	 */
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	    /* Copy (escaping chars) record into temp buffer */
6567c478bd9Sstevel@tonic-gate 	    size = (strlen(rec->attrstr)*2)+1;		/* Max rec size */
6577c478bd9Sstevel@tonic-gate 	    if (buf = malloc(size+1)) {
6587c478bd9Sstevel@tonic-gate 		/* Alloc space */
6597c478bd9Sstevel@tonic-gate 		p = strcatesc(buf, rec->attrstr);	/* Copy "escaped" */
6607c478bd9Sstevel@tonic-gate 		*(p-2) = '\n';				/* Unescape last \n */
6617c478bd9Sstevel@tonic-gate 		*(p-1) = '\0';				/* Terminate string */
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 		/* Write the record */
6647c478bd9Sstevel@tonic-gate 		count = fputs(buf, stream);
6657c478bd9Sstevel@tonic-gate 		free(buf);
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	    } else count = EOF;  /* malloc() failed */
6687c478bd9Sstevel@tonic-gate 	}
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	else {
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 		/*
6737c478bd9Sstevel@tonic-gate 		 * Record is a data record
6747c478bd9Sstevel@tonic-gate 		 */
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 		/*
6777c478bd9Sstevel@tonic-gate 		 * Figure out maximum amount of space you're going to need.
6787c478bd9Sstevel@tonic-gate 		 * (Assume every escapable character is escaped to determine the
6797c478bd9Sstevel@tonic-gate 		 * maximum size needed)
6807c478bd9Sstevel@tonic-gate 		 */
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	    if (rec->cdevice)
6837c478bd9Sstevel@tonic-gate 		size += (strlen(rec->cdevice)*2) + 1;	/* cdevice: */
6847c478bd9Sstevel@tonic-gate 	    if (rec->bdevice)
6857c478bd9Sstevel@tonic-gate 		size += (strlen(rec->bdevice)*2) + 1;	/* bdevice: */
6867c478bd9Sstevel@tonic-gate 	    if (rec->pathname)
6877c478bd9Sstevel@tonic-gate 		size += (strlen(rec->pathname)*2) + 1;	/* pathname: */
6887c478bd9Sstevel@tonic-gate 	    if ((attrval = rec->attrlist) != NULL) do {	/* Attributes */
6897c478bd9Sstevel@tonic-gate 		if (attrval->attr)
6907c478bd9Sstevel@tonic-gate 			size += (strlen(attrval->attr)*2);	    /* attr */
6917c478bd9Sstevel@tonic-gate 		if (attrval->val) {
6927c478bd9Sstevel@tonic-gate 			/* val & '="" ' or val & '=""\n' */
6937c478bd9Sstevel@tonic-gate 			size += (strlen(attrval->val)*2) +4;
6947c478bd9Sstevel@tonic-gate 		}
6957c478bd9Sstevel@tonic-gate 	    } while ((attrval = attrval->next) != NULL);    /* Next attr/val */
6967c478bd9Sstevel@tonic-gate 	    else size++;		/* Else make room for trailing '\n' */
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	    /* Alloc space for "escaped" record */
6997c478bd9Sstevel@tonic-gate 	    if (buf = malloc(size+1)) {
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 		/* Initializations */
7027c478bd9Sstevel@tonic-gate 		p = buf;
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 		/* Write the alias ("alias" attribute) */
7057c478bd9Sstevel@tonic-gate 		p = strcatesc(p, rec->alias);
7067c478bd9Sstevel@tonic-gate 		*p++ = ':';
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 		/* Write the character device ("cdevice" attribute) */
7097c478bd9Sstevel@tonic-gate 		if (rec->cdevice) p = strcatesc(p, rec->cdevice);
7107c478bd9Sstevel@tonic-gate 		*p++ = ':';
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 		/* Write the block device ("bdevice" attribute) */
7137c478bd9Sstevel@tonic-gate 		if (rec->bdevice) p = strcatesc(p, rec->bdevice);
7147c478bd9Sstevel@tonic-gate 		*p++ = ':';
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 		/* Write the pathname ("pathname" attribute) */
7177c478bd9Sstevel@tonic-gate 		if (rec->pathname) p = strcatesc(p, rec->pathname);
7187c478bd9Sstevel@tonic-gate 		*p++ = ':';
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 		/* Write the rest of the attributes */
7217c478bd9Sstevel@tonic-gate 		if ((attrval = rec->attrlist) != NULL)
7227c478bd9Sstevel@tonic-gate 		    do {
7237c478bd9Sstevel@tonic-gate 			p = strcatesc(p, attrval->attr);
7247c478bd9Sstevel@tonic-gate 			*p++ = '=';
7257c478bd9Sstevel@tonic-gate 			*p++ = '"';
7267c478bd9Sstevel@tonic-gate 			p = strcatesc(p, attrval->val);
7277c478bd9Sstevel@tonic-gate 			*p++ = '"';
7287c478bd9Sstevel@tonic-gate 			if ((attrval = attrval->next) != NULL)
7297c478bd9Sstevel@tonic-gate 			    *p++ = ' ';
7307c478bd9Sstevel@tonic-gate 		    } while (attrval);
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 		/* Terminate the record */
7337c478bd9Sstevel@tonic-gate 		*p++ = '\n';
7347c478bd9Sstevel@tonic-gate 		*p = '\0';
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 		/* Write the record */
7377c478bd9Sstevel@tonic-gate 		count = fputs(buf, stream);
7387c478bd9Sstevel@tonic-gate 		free(buf);
7397c478bd9Sstevel@tonic-gate 	    } else count = EOF;  /* malloc() failed */
7407c478bd9Sstevel@tonic-gate 	}
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	/* Finished */
7437c478bd9Sstevel@tonic-gate 	return (count);
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate /*
7477c478bd9Sstevel@tonic-gate  *  int _adddevtabrec(alias, attrval)
7487c478bd9Sstevel@tonic-gate  *	char   *alias
7497c478bd9Sstevel@tonic-gate  *	char  **attrval
7507c478bd9Sstevel@tonic-gate  *
7517c478bd9Sstevel@tonic-gate  *	This function adds a record to the device table.  That record will
7527c478bd9Sstevel@tonic-gate  *	have the alias <alias> and will have the attributes described in
7537c478bd9Sstevel@tonic-gate  *	the list referenced by <attrval>.
7547c478bd9Sstevel@tonic-gate  *
7557c478bd9Sstevel@tonic-gate  *	It always adds the record to the end of the table.
7567c478bd9Sstevel@tonic-gate  *
7577c478bd9Sstevel@tonic-gate  *  Arguments:
7587c478bd9Sstevel@tonic-gate  *	alias		The alias of the device whose description is being
7597c478bd9Sstevel@tonic-gate  *			added to the device table.
7607c478bd9Sstevel@tonic-gate  *	attrval		The pointer to the first item of a list of attributes
7617c478bd9Sstevel@tonic-gate  *			defining the device whose description is being added.
7627c478bd9Sstevel@tonic-gate  *			(This value may be (char **) NULL).
7637c478bd9Sstevel@tonic-gate  *
7647c478bd9Sstevel@tonic-gate  *  Returns:  int
7657c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE with errno set otherwise.
7667c478bd9Sstevel@tonic-gate  */
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate int
_adddevtabrec(char * alias,char ** attrval)7697c478bd9Sstevel@tonic-gate _adddevtabrec(
7707c478bd9Sstevel@tonic-gate 	char   *alias,			/* Alias to add to the device table */
7717c478bd9Sstevel@tonic-gate 	char  **attrval)		/* Attributes for that device */
7727c478bd9Sstevel@tonic-gate {
7737c478bd9Sstevel@tonic-gate 	/* Automatic data */
7747c478bd9Sstevel@tonic-gate 	struct devtabent	*devtabent;	/* Ptr to dev tab entry */
7757c478bd9Sstevel@tonic-gate 	int			olderrno;	/* Errno on entry */
7767c478bd9Sstevel@tonic-gate 	int			noerr;		/* FLAG, TRUE if all's well */
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	/* Validate the device alias.  Error (EINVAL) if it's not valid */
7797c478bd9Sstevel@tonic-gate 	if (!_validalias(alias)) {
7807c478bd9Sstevel@tonic-gate 	    errno = EINVAL;
7817c478bd9Sstevel@tonic-gate 	    return (FALSE);
7827c478bd9Sstevel@tonic-gate 	}
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 	/*
7857c478bd9Sstevel@tonic-gate 	 * Lock the device table.  This only returns if the table is locked or
7867c478bd9Sstevel@tonic-gate 	 * some error occurred.  It waits until the table is available.
7877c478bd9Sstevel@tonic-gate 	 */
7887c478bd9Sstevel@tonic-gate 	if (!lkdevtab("a+", F_WRLCK))
7897c478bd9Sstevel@tonic-gate 		return (FALSE);
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	/* Make sure that the alias isn't already in the table */
7927c478bd9Sstevel@tonic-gate 	noerr = TRUE;
7937c478bd9Sstevel@tonic-gate 	olderrno = errno;
7947c478bd9Sstevel@tonic-gate 	if (devtabent = _getdevrec(alias)) {
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 	    /* The alias is already in the table */
7977c478bd9Sstevel@tonic-gate 	    _freedevtabent(devtabent);		/* Free device table info */
7987c478bd9Sstevel@tonic-gate 	    errno = EEXIST;			/* Set errno, entry exists */
7997c478bd9Sstevel@tonic-gate 	    noerr = FALSE;			/* All's not well */
8007c478bd9Sstevel@tonic-gate 	} else if ((errno == ENOENT) || (errno == ENODEV)) {
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 	    /* The alias wasn't in the table or there wasn't a table. */
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 	    errno = olderrno;			/* Reset errno */
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 	    /* Build a struct devtabent that describes the new alias */
8077c478bd9Sstevel@tonic-gate 	    if (devtabent = mkdevtabent(alias, attrval)) {
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 		/* Position to the end of the existing table */
8107c478bd9Sstevel@tonic-gate 		if (fseek(oam_devtab, 0, SEEK_END) == 0)
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 		    /* Write the new entry */
8137c478bd9Sstevel@tonic-gate 		    noerr = (_putdevtabrec(oam_devtab, devtabent) != EOF);
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 		/* Free the info we just wrote */
8167c478bd9Sstevel@tonic-gate 		_freedevtabent(devtabent);
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;	/* mkdevtabent() failed */
8197c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;		/* Some odd error, _devtab */
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 	/* Unlock and close the device table */
8227c478bd9Sstevel@tonic-gate 	(void) unlkdevtab();
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 	/* Fini */
8257c478bd9Sstevel@tonic-gate 	return (noerr);
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate /*
8297c478bd9Sstevel@tonic-gate  * int _moddevtabrec(device, attrval)
8307c478bd9Sstevel@tonic-gate  *	char   *device
8317c478bd9Sstevel@tonic-gate  *	char  **attrval
8327c478bd9Sstevel@tonic-gate  *
8337c478bd9Sstevel@tonic-gate  *	This function modifies the description for the specified device
8347c478bd9Sstevel@tonic-gate  *	so that it has the attributes and values as specified in the
8357c478bd9Sstevel@tonic-gate  *	given list.
8367c478bd9Sstevel@tonic-gate  *
8377c478bd9Sstevel@tonic-gate  *  Arguments:
8387c478bd9Sstevel@tonic-gate  *	device		The name of the device whose description
8397c478bd9Sstevel@tonic-gate  *			is being modified
8407c478bd9Sstevel@tonic-gate  *	attrval		The first attr/val value in the list (attr=val) of
8417c478bd9Sstevel@tonic-gate  *			the attributes that are to change
8427c478bd9Sstevel@tonic-gate  *
8437c478bd9Sstevel@tonic-gate  *  Returns:  int
8447c478bd9Sstevel@tonic-gate  *	TRUE if all went well, FALSE with errno set otherwise
8457c478bd9Sstevel@tonic-gate  */
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate int
_moddevtabrec(char * device,char ** attrval)8487c478bd9Sstevel@tonic-gate _moddevtabrec(
8497c478bd9Sstevel@tonic-gate 	char   *device,			/* Device to modify */
8507c478bd9Sstevel@tonic-gate 	char  **attrval)		/* Attributes to add or change */
8517c478bd9Sstevel@tonic-gate {
8527c478bd9Sstevel@tonic-gate 	/* Automatic data */
8537c478bd9Sstevel@tonic-gate 	FILE			*fd;	/* File ptr, new device table */
8547c478bd9Sstevel@tonic-gate 	struct devtabent	*ent;	/* Device's current description */
8557c478bd9Sstevel@tonic-gate 	struct devtabent	*chg;	/* Changes to make to description */
8567c478bd9Sstevel@tonic-gate 	struct attrval		*new;	/* New attribute/value desc */
8577c478bd9Sstevel@tonic-gate 	struct attrval		*old;	/* Old attribute/value desc */
8587c478bd9Sstevel@tonic-gate 	struct attrval		*newnew; /* Next "new" value to look at */
8597c478bd9Sstevel@tonic-gate 	struct attrval		*prevnew; /* Previous item in the 'new' list */
8607c478bd9Sstevel@tonic-gate 	char			*tname;	/* name of temp devtab file */
8617c478bd9Sstevel@tonic-gate 	int			noerr;	/* FLAG, TRUE if all's well */
8627c478bd9Sstevel@tonic-gate 	int			found;	/* FLAG, TRUE if attr found for dev */
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	/* Lock the device table */
8657c478bd9Sstevel@tonic-gate 	if (!lkdevtab("r", F_WRLCK))
8667c478bd9Sstevel@tonic-gate 		return (FALSE);
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate 	/* No problems (so far) */
8697c478bd9Sstevel@tonic-gate 	noerr = TRUE;
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	/* Get the entry to modify */
8727c478bd9Sstevel@tonic-gate 	if (ent = _getdevrec(device)) {
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	    /* Build a structure describing the changes */
8757c478bd9Sstevel@tonic-gate 	    if (chg = mkdevtabent(device, attrval)) {
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 		/* If the "cdevice" field is specified, change it */
8787c478bd9Sstevel@tonic-gate 		if (chg->cdevice) {
8797c478bd9Sstevel@tonic-gate 		    if (ent->cdevice) free(ent->cdevice);
8807c478bd9Sstevel@tonic-gate 		    ent->cdevice = chg->cdevice;
8817c478bd9Sstevel@tonic-gate 		    chg->cdevice = NULL;
8827c478bd9Sstevel@tonic-gate 		}
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 		/* If the "bdevice" field is specified, change it */
8857c478bd9Sstevel@tonic-gate 		if (chg->bdevice) {
8867c478bd9Sstevel@tonic-gate 		    if (ent->bdevice) free(ent->bdevice);
8877c478bd9Sstevel@tonic-gate 		    ent->bdevice = chg->bdevice;
8887c478bd9Sstevel@tonic-gate 		    chg->bdevice = NULL;
8897c478bd9Sstevel@tonic-gate 		}
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 		/* If the "pathname" field is specified, change it */
8927c478bd9Sstevel@tonic-gate 		if (chg->pathname) {
8937c478bd9Sstevel@tonic-gate 		    if (ent->pathname) free(ent->pathname);
8947c478bd9Sstevel@tonic-gate 		    ent->pathname = chg->pathname;
8957c478bd9Sstevel@tonic-gate 		    chg->pathname = NULL;
8967c478bd9Sstevel@tonic-gate 		}
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 		/* Change the other attributes (if any) */
8997c478bd9Sstevel@tonic-gate 		if (ent->attrlist) {
9007c478bd9Sstevel@tonic-gate 		    prevnew = NULL;
9017c478bd9Sstevel@tonic-gate 		    if ((new = chg->attrlist) != NULL) do {
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 			found = FALSE;
9047c478bd9Sstevel@tonic-gate 			for (old = ent->attrlist; !found && old;
9057c478bd9Sstevel@tonic-gate 			    old = old->next) {
9067c478bd9Sstevel@tonic-gate 			    if (strcmp(old->attr, new->attr) == 0) {
9077c478bd9Sstevel@tonic-gate 				found = TRUE;
9087c478bd9Sstevel@tonic-gate 				free(old->val);
9097c478bd9Sstevel@tonic-gate 				old->val = new->val;
9107c478bd9Sstevel@tonic-gate 				new->val = NULL;
9117c478bd9Sstevel@tonic-gate 			    }
9127c478bd9Sstevel@tonic-gate 			}   /* Loop through the existing attribute list */
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 			/*
9157c478bd9Sstevel@tonic-gate 			 * If the attribute wasn't found, add it to the list
9167c478bd9Sstevel@tonic-gate 			 * of attributes for the device.  If it was found, just
9177c478bd9Sstevel@tonic-gate 			 * bump to the next one and look for it
9187c478bd9Sstevel@tonic-gate 			 */
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 			if (!found) {
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 			/*
9237c478bd9Sstevel@tonic-gate 			 * Not found.  Move attr/val description to the
9247c478bd9Sstevel@tonic-gate 			 * device's list of attributes
9257c478bd9Sstevel@tonic-gate 			 */
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 			    if (prevnew) prevnew->next = new->next;
9287c478bd9Sstevel@tonic-gate 			    else chg->attrlist = new->next;
9297c478bd9Sstevel@tonic-gate 			    newnew = new->next;
9307c478bd9Sstevel@tonic-gate 			    new->next = ent->attrlist;
9317c478bd9Sstevel@tonic-gate 			    ent->attrlist = new;
9327c478bd9Sstevel@tonic-gate 			    new = newnew;
9337c478bd9Sstevel@tonic-gate 			} else {
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 			    /* Attribute changed, bump to the next one */
9367c478bd9Sstevel@tonic-gate 			    prevnew = new;
9377c478bd9Sstevel@tonic-gate 			    new = new->next;
9387c478bd9Sstevel@tonic-gate 			}
9397c478bd9Sstevel@tonic-gate 		    } while (new);  /* Loop for each attr to add or modify */
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 		} else {
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate 		    /* Device had no attributes -- add entire list */
9447c478bd9Sstevel@tonic-gate 		    ent->attrlist = chg->attrlist;
9457c478bd9Sstevel@tonic-gate 		    chg->attrlist = NULL;
9467c478bd9Sstevel@tonic-gate 		}
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate 		/* Free the structure containing the changes */
9497c478bd9Sstevel@tonic-gate 		_freedevtabent(chg);
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;   /* Couldn't build changes struct */
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 	    /* If there hasn't been an error (so far), write the new record */
9547c478bd9Sstevel@tonic-gate 	    if (noerr) {
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 		/* Open the new device table */
9577c478bd9Sstevel@tonic-gate 		if (fd = opennewdevtab(&tname)) {
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 		/*
9607c478bd9Sstevel@tonic-gate 		 * For each entry in the existing table, write that entry
9617c478bd9Sstevel@tonic-gate 		 * to the new table.  If the entry is the one being
9627c478bd9Sstevel@tonic-gate 		 * modified, write the modified entry instead of the
9637c478bd9Sstevel@tonic-gate 		 * original entry.
9647c478bd9Sstevel@tonic-gate 		 */
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 		    _setdevtab();		/* Rewind existing table */
9677c478bd9Sstevel@tonic-gate 		    chg = ent;			/* Remember new record */
9687c478bd9Sstevel@tonic-gate 		    while (((ent = _getdevtabent()) != NULL) && noerr) {
9697c478bd9Sstevel@tonic-gate 			if (ent->entryno != chg->entryno)
9707c478bd9Sstevel@tonic-gate 			    noerr = _putdevtabrec(fd, ent) != EOF;
9717c478bd9Sstevel@tonic-gate 			else noerr = _putdevtabrec(fd, chg) != EOF;
9727c478bd9Sstevel@tonic-gate 			_freedevtabent(ent);
9737c478bd9Sstevel@tonic-gate 		    }
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 		/*
9767c478bd9Sstevel@tonic-gate 		 * If we successfully generated the new table, make it the
9777c478bd9Sstevel@tonic-gate 		 * new system device table.  Otherwise, just remove the
9787c478bd9Sstevel@tonic-gate 		 * temporary file we've created.
9797c478bd9Sstevel@tonic-gate 		 */
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 		    if (noerr) {
9827c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
9837c478bd9Sstevel@tonic-gate 			noerr = mknewdevtab(tname);
9847c478bd9Sstevel@tonic-gate 		    } else {
9857c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
9867c478bd9Sstevel@tonic-gate 			(void) rmnewdevtab(tname);
9877c478bd9Sstevel@tonic-gate 		    }
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 		    /* Free the changed device structure */
9907c478bd9Sstevel@tonic-gate 		    _freedevtabent(chg);
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate 		}   /* if (_opennewdevtab()) */
9937c478bd9Sstevel@tonic-gate 		else noerr = FALSE;
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 	    } else _freedevtabent(ent);  /* if (noerr) */
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;	/* Device not found? */
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate 	/* Finished.  Unlock the device table and quit */
10007c478bd9Sstevel@tonic-gate 	(void) unlkdevtab();
10017c478bd9Sstevel@tonic-gate 	return (noerr);
10027c478bd9Sstevel@tonic-gate }
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate /*
10057c478bd9Sstevel@tonic-gate  * int _rmdevtabrec(device)
10067c478bd9Sstevel@tonic-gate  *	char   *device
10077c478bd9Sstevel@tonic-gate  *
10087c478bd9Sstevel@tonic-gate  *	This function removes the record in the device table for the specified
10097c478bd9Sstevel@tonic-gate  *	device.
10107c478bd9Sstevel@tonic-gate  *
10117c478bd9Sstevel@tonic-gate  *  Arguments:
10127c478bd9Sstevel@tonic-gate  *	device	The device (alias, cdevice, bdevice, pathname, or link to one)
10137c478bd9Sstevel@tonic-gate  *		whose entry is to be removed
10147c478bd9Sstevel@tonic-gate  *
10157c478bd9Sstevel@tonic-gate  *  Returns:  int
10167c478bd9Sstevel@tonic-gate  *	Success indicator:  TRUE if successful, FALSE with errno set otherwise.
10177c478bd9Sstevel@tonic-gate  */
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate int
_rmdevtabrec(char * device)10207c478bd9Sstevel@tonic-gate _rmdevtabrec(char *device)		/* Device to remove */
10217c478bd9Sstevel@tonic-gate {
10227c478bd9Sstevel@tonic-gate 	struct devtabent	*rment;
10237c478bd9Sstevel@tonic-gate 	struct devtabent	*devtabent;
10247c478bd9Sstevel@tonic-gate 	char			*tempname;
10257c478bd9Sstevel@tonic-gate 	FILE			*fd;
10267c478bd9Sstevel@tonic-gate 	int			noerr;
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 	if (!lkdevtab("r", F_WRLCK))
10297c478bd9Sstevel@tonic-gate 		return (FALSE);
10307c478bd9Sstevel@tonic-gate 	noerr = TRUE;
10317c478bd9Sstevel@tonic-gate 	if (rment = _getdevrec(device)) {
10327c478bd9Sstevel@tonic-gate 	    if (fd = opennewdevtab(&tempname)) {
10337c478bd9Sstevel@tonic-gate 		_setdevtab();
10347c478bd9Sstevel@tonic-gate 		while (((devtabent = _getdevtabent()) != NULL) && noerr) {
10357c478bd9Sstevel@tonic-gate 		    if (devtabent->entryno != rment->entryno)
10367c478bd9Sstevel@tonic-gate 			noerr = _putdevtabrec(fd, devtabent) != EOF;
10377c478bd9Sstevel@tonic-gate 		    _freedevtabent(devtabent);
10387c478bd9Sstevel@tonic-gate 		}
10397c478bd9Sstevel@tonic-gate 		if (noerr) {
10407c478bd9Sstevel@tonic-gate 		    (void) fclose(fd);
10417c478bd9Sstevel@tonic-gate 		    noerr = mknewdevtab(tempname);
10427c478bd9Sstevel@tonic-gate 		} else {
10437c478bd9Sstevel@tonic-gate 		    (void) fclose(fd);
10447c478bd9Sstevel@tonic-gate 		    (void) rmnewdevtab(tempname);
10457c478bd9Sstevel@tonic-gate 		}
10467c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;
10477c478bd9Sstevel@tonic-gate 	    _freedevtabent(rment);
10487c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;
10497c478bd9Sstevel@tonic-gate 	(void) unlkdevtab();
10507c478bd9Sstevel@tonic-gate 	return (noerr);
10517c478bd9Sstevel@tonic-gate }
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate /*
10547c478bd9Sstevel@tonic-gate  * int _rmdevtabattrs(device, attributes, notfounds)
10557c478bd9Sstevel@tonic-gate  *	char   *device
10567c478bd9Sstevel@tonic-gate  *	char  **attributes
10577c478bd9Sstevel@tonic-gate  *	char ***notfounds
10587c478bd9Sstevel@tonic-gate  *
10597c478bd9Sstevel@tonic-gate  *	Remove the specified attributes from the specified device.  The
10607c478bd9Sstevel@tonic-gate  *	device is specified by <device>, <attributes> is the address of
10617c478bd9Sstevel@tonic-gate  *	the first char * in the list of char * pointing to the attributes
10627c478bd9Sstevel@tonic-gate  *	to remove from the device, and <notfounds> is the address of a
10637c478bd9Sstevel@tonic-gate  *	char ** to put the address of the first element in the malloc()ed
10647c478bd9Sstevel@tonic-gate  *	list of (char *) pointing to requested attributes that were not
10657c478bd9Sstevel@tonic-gate  *	defined for the device <device>.
10667c478bd9Sstevel@tonic-gate  *
10677c478bd9Sstevel@tonic-gate  *  Arguments:
10687c478bd9Sstevel@tonic-gate  *	device		The device from which attributes are to be removed
10697c478bd9Sstevel@tonic-gate  *	attributes	The address of the first element in the list of
10707c478bd9Sstevel@tonic-gate  *			attributes to remove.  This list is terminated by
10717c478bd9Sstevel@tonic-gate  *			(char *) NULL.
10727c478bd9Sstevel@tonic-gate  *	notfounds	The place to put the address of the list of addresses
10737c478bd9Sstevel@tonic-gate  *			referencing the requested attributes that are not
10747c478bd9Sstevel@tonic-gate  *			defined for the specified device.
10757c478bd9Sstevel@tonic-gate  *
10767c478bd9Sstevel@tonic-gate  *  Returns: int
10777c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE with errno set otherwise.
10787c478bd9Sstevel@tonic-gate  *
10797c478bd9Sstevel@tonic-gate  *  Notes:
10807c478bd9Sstevel@tonic-gate  *    -	"alias" may not be undefined
10817c478bd9Sstevel@tonic-gate  *    - "cdevice", "bdevice", and "pathname" are made "null", not really
10827c478bd9Sstevel@tonic-gate  *	undefined
10837c478bd9Sstevel@tonic-gate  */
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate int
_rmdevtabattrs(char * device,char ** attributes,char *** notfounds)10867c478bd9Sstevel@tonic-gate _rmdevtabattrs(
10877c478bd9Sstevel@tonic-gate 	char   *device,			/* Device to modify */
10887c478bd9Sstevel@tonic-gate 	char  **attributes,		/* Attributes to remove */
10897c478bd9Sstevel@tonic-gate 	char ***notfounds)		/* Attributes req'd but not found */
10907c478bd9Sstevel@tonic-gate {
10917c478bd9Sstevel@tonic-gate 	/* Automatics */
10927c478bd9Sstevel@tonic-gate 	char			**pnxt;		/* Ptr to next attribute */
10937c478bd9Sstevel@tonic-gate 	char			**pp;		/* Ptr to current attr name */
10947c478bd9Sstevel@tonic-gate 	struct devtabent	*modent;	/* Entry being modified */
10957c478bd9Sstevel@tonic-gate 	struct devtabent	*devtabent;	/* Entry being copied */
10967c478bd9Sstevel@tonic-gate 	struct attrval		*attrval;	/* Ptr to attr/val desc */
10977c478bd9Sstevel@tonic-gate 	struct attrval		*prevattrval;	/* Ptr to prev attr/val */
10987c478bd9Sstevel@tonic-gate 	FILE			*fd;		/* File desc, temp file */
10997c478bd9Sstevel@tonic-gate 	char			*tempname;	/* Name of temp file */
11007c478bd9Sstevel@tonic-gate 	int			nattrs;		/* Number of attrs to remove */
11017c478bd9Sstevel@tonic-gate 	int			nobaderr;	/* TRUE if no fatal error */
11027c478bd9Sstevel@tonic-gate 	int			noerr;		/* TRUE if no non-fatal error */
11037c478bd9Sstevel@tonic-gate 	int			found;		/* TRUE if attribute found */
11047c478bd9Sstevel@tonic-gate 	int			nonotfounds;	/* TRUE if no attrs not fount */
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	/* Initializations */
11087c478bd9Sstevel@tonic-gate 	nobaderr = TRUE;
11097c478bd9Sstevel@tonic-gate 	noerr = TRUE;
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate 	/* Count attributes to remove -- make sure "alias" isn't specified */
11127c478bd9Sstevel@tonic-gate 	for (pp = attributes, nattrs = 0; *pp; pp++, nattrs++)
11137c478bd9Sstevel@tonic-gate 	    if (strcmp(*pp, DTAB_ALIAS) == 0) {
11147c478bd9Sstevel@tonic-gate 		*notfounds = NULL;
11157c478bd9Sstevel@tonic-gate 		errno = EINVAL;
11167c478bd9Sstevel@tonic-gate 		return (FALSE);
11177c478bd9Sstevel@tonic-gate 	    }
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	/* Lock the device table */
11207c478bd9Sstevel@tonic-gate 	if (!lkdevtab("r", F_WRLCK))
11217c478bd9Sstevel@tonic-gate 		return (FALSE);
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	/* Is there a record for the requested device? */
11247c478bd9Sstevel@tonic-gate 	if (modent = _getdevrec(device)) {
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 	    /* Record found.  Try to modify it */
11277c478bd9Sstevel@tonic-gate 	    nonotfounds = TRUE;
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate 	    /* For each of the attributes in the attribute list ... */
11307c478bd9Sstevel@tonic-gate 	    for (pp = attributes; nobaderr && *pp; pp++) {
11317c478bd9Sstevel@tonic-gate 
11327c478bd9Sstevel@tonic-gate 		/*
11337c478bd9Sstevel@tonic-gate 		 * Modify the device description, removing the requested
11347c478bd9Sstevel@tonic-gate 		 * attributes from the structure
11357c478bd9Sstevel@tonic-gate 		 */
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 		found = FALSE;				/* Not found yet */
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 		/* If it's the "cdevice" attribute, make it a null-string */
11407c478bd9Sstevel@tonic-gate 		if (strcmp(*pp, DTAB_CDEVICE) == 0) {
11417c478bd9Sstevel@tonic-gate 		    if (modent->cdevice) {
11427c478bd9Sstevel@tonic-gate 			free(modent->cdevice);
11437c478bd9Sstevel@tonic-gate 			modent->cdevice = NULL;
11447c478bd9Sstevel@tonic-gate 		    }
11457c478bd9Sstevel@tonic-gate 		    found = TRUE;
11467c478bd9Sstevel@tonic-gate 		}
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate 		/* If it's the "bdevice" attribute, make it a null-string */
11497c478bd9Sstevel@tonic-gate 		else if (strcmp(*pp, DTAB_BDEVICE) == 0) {
11507c478bd9Sstevel@tonic-gate 		    if (modent->bdevice) {
11517c478bd9Sstevel@tonic-gate 			free(modent->bdevice);
11527c478bd9Sstevel@tonic-gate 			modent->bdevice = NULL;
11537c478bd9Sstevel@tonic-gate 		    }
11547c478bd9Sstevel@tonic-gate 		    found = TRUE;
11557c478bd9Sstevel@tonic-gate 		}
11567c478bd9Sstevel@tonic-gate 
11577c478bd9Sstevel@tonic-gate 		/* If it's the "pathname" attribute, make it a null-string */
11587c478bd9Sstevel@tonic-gate 		else if (strcmp(*pp, DTAB_PATHNAME) == 0) {
11597c478bd9Sstevel@tonic-gate 		    if (modent->pathname) {
11607c478bd9Sstevel@tonic-gate 			free(modent->pathname);
11617c478bd9Sstevel@tonic-gate 			modent->pathname = NULL;
11627c478bd9Sstevel@tonic-gate 		    }
11637c478bd9Sstevel@tonic-gate 		    found = TRUE;
11647c478bd9Sstevel@tonic-gate 		}
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 		/* Must be one of the other "auxilliary" attributes */
11677c478bd9Sstevel@tonic-gate 		else {
11687c478bd9Sstevel@tonic-gate 
11697c478bd9Sstevel@tonic-gate 		    /* Search the attribute list for the attribute */
11707c478bd9Sstevel@tonic-gate 		    prevattrval = NULL;
11717c478bd9Sstevel@tonic-gate 		    if ((attrval = modent->attrlist) != NULL) do {
11727c478bd9Sstevel@tonic-gate 			if (strcmp(*pp, attrval->attr) == 0) {
11737c478bd9Sstevel@tonic-gate 
11747c478bd9Sstevel@tonic-gate 			    /* Found.  Remove from attribute list */
11757c478bd9Sstevel@tonic-gate 			    found = TRUE;
11767c478bd9Sstevel@tonic-gate 			    free(attrval->attr);
11777c478bd9Sstevel@tonic-gate 			    free(attrval->val);
11787c478bd9Sstevel@tonic-gate 			    if (prevattrval) {
11797c478bd9Sstevel@tonic-gate 				prevattrval->next = attrval->next;
11807c478bd9Sstevel@tonic-gate 				free(attrval);
11817c478bd9Sstevel@tonic-gate 				attrval = prevattrval->next;
11827c478bd9Sstevel@tonic-gate 			    } else {
11837c478bd9Sstevel@tonic-gate 				modent->attrlist = attrval->next;
11847c478bd9Sstevel@tonic-gate 				free(attrval);
11857c478bd9Sstevel@tonic-gate 				attrval = modent->attrlist;
11867c478bd9Sstevel@tonic-gate 			    }
11877c478bd9Sstevel@tonic-gate 			} else {
11887c478bd9Sstevel@tonic-gate 			    prevattrval = attrval;	/* Advance to next */
11897c478bd9Sstevel@tonic-gate 			    attrval = attrval->next;
11907c478bd9Sstevel@tonic-gate 			}
11917c478bd9Sstevel@tonic-gate 		    } while (!found && attrval);
11927c478bd9Sstevel@tonic-gate 
11937c478bd9Sstevel@tonic-gate 		}   /* End attribute search loop */
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 		/*
11967c478bd9Sstevel@tonic-gate 		 * If the requested attribute wasn't defined for the device,
11977c478bd9Sstevel@tonic-gate 		 * put it in the list of attributes not found
11987c478bd9Sstevel@tonic-gate 		 */
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 		if (!found) {
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate 			/*
12037c478bd9Sstevel@tonic-gate 			 * If there's no list (yet), alloc enough space for
12047c478bd9Sstevel@tonic-gate 			 * the list
12057c478bd9Sstevel@tonic-gate 			 */
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 		    if (nonotfounds)
12087c478bd9Sstevel@tonic-gate 			if (*notfounds = malloc(sizeof (char **)*(nattrs+1))) {
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 			    /* List allocated -- put in the first entry */
12117c478bd9Sstevel@tonic-gate 			    nonotfounds = FALSE;
12127c478bd9Sstevel@tonic-gate 			    pnxt = *notfounds;
12137c478bd9Sstevel@tonic-gate 			    if (*pnxt = malloc(strlen(*pp)+1)) {
12147c478bd9Sstevel@tonic-gate 				errno = EINVAL;
12157c478bd9Sstevel@tonic-gate 				noerr = FALSE;
12167c478bd9Sstevel@tonic-gate 				(void) strcpy(*pnxt++, *pp);
12177c478bd9Sstevel@tonic-gate 			    } else {
12187c478bd9Sstevel@tonic-gate 				/* malloc() failed, free list */
12197c478bd9Sstevel@tonic-gate 				free(*notfounds);
12207c478bd9Sstevel@tonic-gate 				*notfounds = NULL;
12217c478bd9Sstevel@tonic-gate 				nonotfounds = TRUE;
12227c478bd9Sstevel@tonic-gate 				nobaderr = FALSE;
12237c478bd9Sstevel@tonic-gate 			    }
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate 			} else nobaderr = FALSE;  /* malloc() failed */
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate 		    else {
12287c478bd9Sstevel@tonic-gate 			/* Already a list, add this attribute to it */
12297c478bd9Sstevel@tonic-gate 			if (*pnxt = malloc(strlen(*pp)+1))
12307c478bd9Sstevel@tonic-gate 			    (void) strcpy(*pnxt++, *pp);
12317c478bd9Sstevel@tonic-gate 			else {
12327c478bd9Sstevel@tonic-gate 			    /* Out of memory, clean up */
12337c478bd9Sstevel@tonic-gate 			    for (pnxt = *notfounds; *pnxt; pnxt++)
12347c478bd9Sstevel@tonic-gate 				free(*pnxt);
12357c478bd9Sstevel@tonic-gate 			    free(*notfounds);
12367c478bd9Sstevel@tonic-gate 			    *notfounds = NULL;
12377c478bd9Sstevel@tonic-gate 			    nonotfounds = TRUE;
12387c478bd9Sstevel@tonic-gate 			    nobaderr = FALSE;
12397c478bd9Sstevel@tonic-gate 			}
12407c478bd9Sstevel@tonic-gate 		    }
12417c478bd9Sstevel@tonic-gate 
12427c478bd9Sstevel@tonic-gate 		}    /* end if (!found) */
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 		/* Terminate the not-found list */
12457c478bd9Sstevel@tonic-gate 		if (!nonotfounds) *pnxt = NULL;
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 	    }	/* end (for each attribute in attribute list) loop */
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 		/*
12517c478bd9Sstevel@tonic-gate 		 * If we haven't seen any problems so far,
12527c478bd9Sstevel@tonic-gate 		 * write the new device table
12537c478bd9Sstevel@tonic-gate 		 */
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 	    if (nobaderr) {
12567c478bd9Sstevel@tonic-gate 
12577c478bd9Sstevel@tonic-gate 		/* Open the new device table */
12587c478bd9Sstevel@tonic-gate 		if (fd = opennewdevtab(&tempname)) {
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 		/*
12617c478bd9Sstevel@tonic-gate 		 * For each entry in the existing table, write that entry
12627c478bd9Sstevel@tonic-gate 		 * to the new table.  If the entry is the one being
12637c478bd9Sstevel@tonic-gate 		 * modified, write the modified entry instead of the
12647c478bd9Sstevel@tonic-gate 		 * original entry.
12657c478bd9Sstevel@tonic-gate 		 */
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate 		    _setdevtab();		/* Rewind existing table */
12687c478bd9Sstevel@tonic-gate 		    while (((devtabent = _getdevtabent()) != NULL) &&
12697c478bd9Sstevel@tonic-gate 			nobaderr) {
12707c478bd9Sstevel@tonic-gate 
12717c478bd9Sstevel@tonic-gate 			if (devtabent->entryno != modent->entryno)
12727c478bd9Sstevel@tonic-gate 			    nobaderr = _putdevtabrec(fd, devtabent) != EOF;
12737c478bd9Sstevel@tonic-gate 			else nobaderr = _putdevtabrec(fd, modent) != EOF;
12747c478bd9Sstevel@tonic-gate 			_freedevtabent(devtabent);
12757c478bd9Sstevel@tonic-gate 		    }
12767c478bd9Sstevel@tonic-gate 
12777c478bd9Sstevel@tonic-gate 		/*
12787c478bd9Sstevel@tonic-gate 		 * If we successfully generated the new table, make it the
12797c478bd9Sstevel@tonic-gate 		 * new system device table.  Otherwise, just remove the
12807c478bd9Sstevel@tonic-gate 		 * temporary file we've created.
12817c478bd9Sstevel@tonic-gate 		 */
12827c478bd9Sstevel@tonic-gate 
12837c478bd9Sstevel@tonic-gate 		    if (nobaderr) {
12847c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
12857c478bd9Sstevel@tonic-gate 			nobaderr = mknewdevtab(tempname);
12867c478bd9Sstevel@tonic-gate 		    } else {
12877c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
12887c478bd9Sstevel@tonic-gate 			(void) rmnewdevtab(tempname);
12897c478bd9Sstevel@tonic-gate 		    }
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 		}   /* if (_opennewdevtab()) */
12927c478bd9Sstevel@tonic-gate 		else nobaderr = FALSE;
12937c478bd9Sstevel@tonic-gate 
12947c478bd9Sstevel@tonic-gate 		/*
12957c478bd9Sstevel@tonic-gate 		 * If there was some error, we need to clean up
12967c478bd9Sstevel@tonic-gate 		 * allocated resources
12977c478bd9Sstevel@tonic-gate 		 */
12987c478bd9Sstevel@tonic-gate 		if (!nobaderr && !nonotfounds) {
12997c478bd9Sstevel@tonic-gate 		    for (pnxt = *notfounds; *pnxt; pnxt++)
13007c478bd9Sstevel@tonic-gate 			free(*pnxt);
13017c478bd9Sstevel@tonic-gate 		    free(*notfounds);
13027c478bd9Sstevel@tonic-gate 		    *notfounds = NULL;
13037c478bd9Sstevel@tonic-gate 		    nonotfounds = TRUE;
13047c478bd9Sstevel@tonic-gate 		}
13057c478bd9Sstevel@tonic-gate 
13067c478bd9Sstevel@tonic-gate 	    }	/* if (nobaderr) */
13077c478bd9Sstevel@tonic-gate 
13087c478bd9Sstevel@tonic-gate 	    /* Free the resources alloc'ed for <device>'s entry */
13097c478bd9Sstevel@tonic-gate 	    _freedevtabent(modent);
13107c478bd9Sstevel@tonic-gate 
13117c478bd9Sstevel@tonic-gate 	} else {
13127c478bd9Sstevel@tonic-gate 	    /* _getdevrec(device) failed */
13137c478bd9Sstevel@tonic-gate 	    nobaderr = FALSE;
13147c478bd9Sstevel@tonic-gate 	    *notfounds = NULL;
13157c478bd9Sstevel@tonic-gate 	}
13167c478bd9Sstevel@tonic-gate 
13177c478bd9Sstevel@tonic-gate 	/* Unlock the device table */
13187c478bd9Sstevel@tonic-gate 	(void) unlkdevtab();
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 	/* We're finished */
13217c478bd9Sstevel@tonic-gate 	return (noerr && nobaderr);
13227c478bd9Sstevel@tonic-gate }
1323