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 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
237c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Copyright (c) 1997, by Sun Microsystems, Inc.
287c478bd9Sstevel@tonic-gate  * All rights reserved.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate  * Globals defined:
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  *	devreserv()	Reserve a set of OA&M devices
377c478bd9Sstevel@tonic-gate  *	devfree()	Free a reserved device
387c478bd9Sstevel@tonic-gate  *	reservdev()	Get a list of reserved devices
397c478bd9Sstevel@tonic-gate  *	_openlkfile()	Opens the lock file
407c478bd9Sstevel@tonic-gate  *	_rsvtabpath()	Get the pathname of the lock table file
417c478bd9Sstevel@tonic-gate  *	_closelkfile()	Closes the lock file
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * Headers referenced:
467c478bd9Sstevel@tonic-gate  *	<sys/types.h>	System data types
477c478bd9Sstevel@tonic-gate  *	<errno.h>	Error definitions (including "errno")
487c478bd9Sstevel@tonic-gate  *	<string.h>	String handling definitions
497c478bd9Sstevel@tonic-gate  *	<fcntl.h>	File control definitions
507c478bd9Sstevel@tonic-gate  *	<unistd.h>	Unix standard value definitions
517c478bd9Sstevel@tonic-gate  *	<devmgmt.h>	Global Device Management definitions
527c478bd9Sstevel@tonic-gate  *	"devtab.h"	Local Device Management definitions
537c478bd9Sstevel@tonic-gate  */
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #include	<sys/types.h>
567c478bd9Sstevel@tonic-gate #include	<errno.h>
577c478bd9Sstevel@tonic-gate #include	<string.h>
587c478bd9Sstevel@tonic-gate #include	<fcntl.h>
597c478bd9Sstevel@tonic-gate #include	<unistd.h>
607c478bd9Sstevel@tonic-gate #include	<stdlib.h>
617c478bd9Sstevel@tonic-gate #include	<devmgmt.h>
627c478bd9Sstevel@tonic-gate #include	"devtab.h"
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  * Local Definitions:
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * Local data types:
717c478bd9Sstevel@tonic-gate  *	struct devlks	Structure that defines locking information (key
727c478bd9Sstevel@tonic-gate  *			with alias name (may be '\0' terminated)
737c478bd9Sstevel@tonic-gate  */
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate struct devlks {
767c478bd9Sstevel@tonic-gate 	int	lk_key;
777c478bd9Sstevel@tonic-gate 	char	lk_alias[((DTAB_MXALIASLN+2)/2)*2];
787c478bd9Sstevel@tonic-gate };
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * Local Functions:
837c478bd9Sstevel@tonic-gate  *	isanullstr()	Is a character string a null string ("")?
847c478bd9Sstevel@tonic-gate  *	getlkcnt()	Get the number of devices locked
857c478bd9Sstevel@tonic-gate  *	locklkfile()	Lock the OA&M Device locking file
867c478bd9Sstevel@tonic-gate  *	getlocks()	Get the device locks from the device-lock file
877c478bd9Sstevel@tonic-gate  *	islocked()	Determines if a device is locked
887c478bd9Sstevel@tonic-gate  *	putlocks()	Close the device locks w/ update
897c478bd9Sstevel@tonic-gate  *	freelkfile()	Close the device locks w/o updating
907c478bd9Sstevel@tonic-gate  *	compresslks()	Compresses the table containing lock info
917c478bd9Sstevel@tonic-gate  */
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate #define	isanullstr(s)	(s[0] == '\0')
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate static	int	locklkfile(short);	/* Lock the lock file */
967c478bd9Sstevel@tonic-gate static	int	getlkcnt(void);		/* Get the number of locked devices */
977c478bd9Sstevel@tonic-gate static	int	getlocks(void);		/* Get the lock information */
987c478bd9Sstevel@tonic-gate static	int	putlocks(char **, int); /* Update lock information */
997c478bd9Sstevel@tonic-gate static	int	freelkfile(void);	/* Free lock information (no update) */
1007c478bd9Sstevel@tonic-gate static	char   *islocked(char *);	/* Determines if a device is locked */
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * Static data
1057c478bd9Sstevel@tonic-gate  */
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate static	struct flock	lkinfo = {0, 0, 0, 0, 0};
1087c478bd9Sstevel@tonic-gate static	struct devlks  *locklist;
1097c478bd9Sstevel@tonic-gate static	int		lockcount;
1107c478bd9Sstevel@tonic-gate static	int		lkfilefd = -1;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate  * char *_rsvtabpath()
1147c478bd9Sstevel@tonic-gate  *
1157c478bd9Sstevel@tonic-gate  *	Determines the pathname of the device reservation table file
1167c478bd9Sstevel@tonic-gate  *
1177c478bd9Sstevel@tonic-gate  *	Uses the following sequential steps:
1187c478bd9Sstevel@tonic-gate  *	     1)	If OAM_DEVLKFILE is defined and is not null, use that as
1197c478bd9Sstevel@tonic-gate  *		the pathname to the file
1207c478bd9Sstevel@tonic-gate  *	     2)	Otherwise, use the devault name found in DVLK_PATH (defined
1217c478bd9Sstevel@tonic-gate  *		in the header file <devtab.h>
1227c478bd9Sstevel@tonic-gate  *
1237c478bd9Sstevel@tonic-gate  *  Arguments:  None
1247c478bd9Sstevel@tonic-gate  *
1257c478bd9Sstevel@tonic-gate  *  Returns:  char *
1267c478bd9Sstevel@tonic-gate  *	A pointer to the filename in malloc()ed memory or (char *) NULL if
1277c478bd9Sstevel@tonic-gate  *	it fails.  "errno" will indicate the error if it fails.
1287c478bd9Sstevel@tonic-gate  */
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate char *
_rsvtabpath(void)1317c478bd9Sstevel@tonic-gate _rsvtabpath(void)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	/* Automatics */
1347c478bd9Sstevel@tonic-gate 	char		*lockname;	/* Name of the lockfile */
1357c478bd9Sstevel@tonic-gate #ifdef	DEBUG
1367c478bd9Sstevel@tonic-gate 	char		*p;		/* Temporary pointer */
1377c478bd9Sstevel@tonic-gate #endif
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate #ifdef	DEBUG
1407c478bd9Sstevel@tonic-gate 	p = getenv(OAM_DEVLKTAB);
1417c478bd9Sstevel@tonic-gate 	if ((p != NULL) && (*p != '\0')) {
1427c478bd9Sstevel@tonic-gate 	    if (lockname = malloc(strlen(p)+1))
1437c478bd9Sstevel@tonic-gate 		(void) strcpy(lockname, p);
1447c478bd9Sstevel@tonic-gate 	} else {
1457c478bd9Sstevel@tonic-gate #endif
1467c478bd9Sstevel@tonic-gate 	    if (lockname = malloc(strlen(DVLK_PATH)+1))
1477c478bd9Sstevel@tonic-gate 		(void) strcpy(lockname, DVLK_PATH);
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate #ifdef	DEBUG
1507c478bd9Sstevel@tonic-gate 	}
1517c478bd9Sstevel@tonic-gate #endif
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	/* Fini -- return a pointer to the lockfile pathname */
1547c478bd9Sstevel@tonic-gate 	return (lockname);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  *  int _openlkfile()
1597c478bd9Sstevel@tonic-gate  *
1607c478bd9Sstevel@tonic-gate  *	The _openlkfile() function opens a device-reservation table file
1617c478bd9Sstevel@tonic-gate  *	for read/write access.
1627c478bd9Sstevel@tonic-gate  *
1637c478bd9Sstevel@tonic-gate  *  Arguments: None
1647c478bd9Sstevel@tonic-gate  *
1657c478bd9Sstevel@tonic-gate  *  Returns:  int
1667c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise.
1677c478bd9Sstevel@tonic-gate  *
1687c478bd9Sstevel@tonic-gate  *  Statics Used:
1697c478bd9Sstevel@tonic-gate  *	lkfilefd	Lock file file descriptor
1707c478bd9Sstevel@tonic-gate  */
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate int
_openlkfile(void)1737c478bd9Sstevel@tonic-gate _openlkfile(void)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate 	/*
1767c478bd9Sstevel@tonic-gate 	 *  Automatic data
1777c478bd9Sstevel@tonic-gate 	 */
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	char   *lockname;		/* Name of the lock file */
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	/* Close the lockfile -- it might be open */
1837c478bd9Sstevel@tonic-gate 	(void) _closelkfile();
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	/* If we can get the name of the lock file ... */
1867c478bd9Sstevel@tonic-gate 	if (lockname = _rsvtabpath()) {
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	    /* Open it */
1897c478bd9Sstevel@tonic-gate 	    lkfilefd = open(lockname, O_RDWR|O_CREAT, 0600);
1907c478bd9Sstevel@tonic-gate 	    free(lockname);
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	}
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	/*  Finis  */
1957c478bd9Sstevel@tonic-gate 	return ((lkfilefd != -1) ? TRUE : FALSE);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate /*
1997c478bd9Sstevel@tonic-gate  * int _closelkfile()
2007c478bd9Sstevel@tonic-gate  *
2017c478bd9Sstevel@tonic-gate  *	Function closes the device-reservation table file and sets the
2027c478bd9Sstevel@tonic-gate  *	necessary external variables to indicate such.
2037c478bd9Sstevel@tonic-gate  *
2047c478bd9Sstevel@tonic-gate  *  Arguments:  None
2057c478bd9Sstevel@tonic-gate  *
2067c478bd9Sstevel@tonic-gate  *  Returns:  int
2077c478bd9Sstevel@tonic-gate  *	Same as close()
2087c478bd9Sstevel@tonic-gate  *
2097c478bd9Sstevel@tonic-gate  *  Statics referenced:
2107c478bd9Sstevel@tonic-gate  *	lkfilefd	The device reservation table file's file descriptor
2117c478bd9Sstevel@tonic-gate  */
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate int
_closelkfile(void)2147c478bd9Sstevel@tonic-gate _closelkfile(void)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate 	/* Automatics */
2177c478bd9Sstevel@tonic-gate 	int	rtnval;		/* Value to return */
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	/* Close the lock file if it's open */
2207c478bd9Sstevel@tonic-gate 	if (lkfilefd != -1) rtnval = close(lkfilefd);
2217c478bd9Sstevel@tonic-gate 	else rtnval = 0;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	/* Indicate that the lock-file is closed */
2247c478bd9Sstevel@tonic-gate 	lkfilefd = -1;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	/* Finis */
2277c478bd9Sstevel@tonic-gate 	return (rtnval);
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate /*
2317c478bd9Sstevel@tonic-gate  *  int locklkfile(lkflag)
2327c478bd9Sstevel@tonic-gate  *	short		lkflag
2337c478bd9Sstevel@tonic-gate  *
2347c478bd9Sstevel@tonic-gate  *	This function locks the device lock file.  If the request cannot
2357c478bd9Sstevel@tonic-gate  *	be serviced, it keeps on trying until it manages to lock the file
2367c478bd9Sstevel@tonic-gate  *	or it encounters an error.
2377c478bd9Sstevel@tonic-gate  *
2387c478bd9Sstevel@tonic-gate  *  Arguments:
2397c478bd9Sstevel@tonic-gate  *	lkflag		Flag (from FCNTL(BA_OS)) indicating which type
2407c478bd9Sstevel@tonic-gate  *			of lock is being requested.  Values that make
2417c478bd9Sstevel@tonic-gate  *			sense:
2427c478bd9Sstevel@tonic-gate  *				F_RDLCK:	Read lock.
2437c478bd9Sstevel@tonic-gate  *				F_WRLCK:	Write lock.
2447c478bd9Sstevel@tonic-gate  *
2457c478bd9Sstevel@tonic-gate  *  Returns: int
2467c478bd9Sstevel@tonic-gate  *	TRUE (non-zero) if the function managed to lock the file, FALSE
2477c478bd9Sstevel@tonic-gate  *	otherwise ("errno" will indicate the problem).
2487c478bd9Sstevel@tonic-gate  *
2497c478bd9Sstevel@tonic-gate  *  Statics used:
2507c478bd9Sstevel@tonic-gate  *	int lkfilefd		File descriptor of the open lock file
2517c478bd9Sstevel@tonic-gate  *	struct flock lkinfo	Structure used by fcntl() to lock a file
2527c478bd9Sstevel@tonic-gate  */
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate static	int
locklkfile(short lkflag)2557c478bd9Sstevel@tonic-gate locklkfile(short lkflag)
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate 	/* Automatic data */
2587c478bd9Sstevel@tonic-gate 	int		noerror;	/* TRUE if no error yet */
2597c478bd9Sstevel@tonic-gate 	int		locked;		/* TRUE if the file is locked */
2607c478bd9Sstevel@tonic-gate 	int		olderrno;	/* Value of errno on call */
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	/* Set up the locking structure */
2647c478bd9Sstevel@tonic-gate 	lkinfo.l_type = lkflag;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	/* Try to lock the file.  If it's locked, wait and try again */
2677c478bd9Sstevel@tonic-gate 	noerror = TRUE;
2687c478bd9Sstevel@tonic-gate 	locked = FALSE;
2697c478bd9Sstevel@tonic-gate 	olderrno = errno;
2707c478bd9Sstevel@tonic-gate 	while (noerror && !locked) {
2717c478bd9Sstevel@tonic-gate 	    if (fcntl(lkfilefd, F_SETLK, &lkinfo) != -1) locked = TRUE;
2727c478bd9Sstevel@tonic-gate 	    else {
2737c478bd9Sstevel@tonic-gate 		if ((errno == EACCES) || (errno == EAGAIN)) {
2747c478bd9Sstevel@tonic-gate 		    errno = olderrno;
2757c478bd9Sstevel@tonic-gate 		    if (sleep(2)) noerror = FALSE;
2767c478bd9Sstevel@tonic-gate 		} else noerror = FALSE;
2777c478bd9Sstevel@tonic-gate 	    }
2787c478bd9Sstevel@tonic-gate 	}
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	/* Return a success flag */
2817c478bd9Sstevel@tonic-gate 	return (locked);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate  *  int getlkcnt()
2867c478bd9Sstevel@tonic-gate  *
2877c478bd9Sstevel@tonic-gate  *	This function extracts the number of currently-locked devices
2887c478bd9Sstevel@tonic-gate  *	from the lock file.
2897c478bd9Sstevel@tonic-gate  *
2907c478bd9Sstevel@tonic-gate  *  Arguments:  None
2917c478bd9Sstevel@tonic-gate  *
2927c478bd9Sstevel@tonic-gate  *  Returns:  int
2937c478bd9Sstevel@tonic-gate  *	The number of devices locked or -1 if an error occurred.
2947c478bd9Sstevel@tonic-gate  *
2957c478bd9Sstevel@tonic-gate  *  Statics used:
2967c478bd9Sstevel@tonic-gate  *	lkfilefd	File descriptor of the open lockfile
2977c478bd9Sstevel@tonic-gate  *
2987c478bd9Sstevel@tonic-gate  *  Assumptions:
2997c478bd9Sstevel@tonic-gate  *    -	The file is positioned to the beginning-of-file
3007c478bd9Sstevel@tonic-gate  */
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate static	int
getlkcnt(void)3037c478bd9Sstevel@tonic-gate getlkcnt(void)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 	/* Automatics */
3067c478bd9Sstevel@tonic-gate 	int	cntread;		/* Number of bytes read */
3077c478bd9Sstevel@tonic-gate 	int	lkcnt;			/* Number of current locks */
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	/* Get the lock count from the file */
3107c478bd9Sstevel@tonic-gate 	cntread = (int)read(lkfilefd, &lkcnt, sizeof (int));
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	/* If there wasn't one, set to 0.  If error, set to -1 */
3137c478bd9Sstevel@tonic-gate 	if (cntread != (int)sizeof (int))
3147c478bd9Sstevel@tonic-gate 		lkcnt = (cntread < 0) ? -1 : 0;
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	/* Return the lock count */
3177c478bd9Sstevel@tonic-gate 	return (lkcnt);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate /*
3217c478bd9Sstevel@tonic-gate  *  int readlocks()
3227c478bd9Sstevel@tonic-gate  *
3237c478bd9Sstevel@tonic-gate  *	The readlocks() function reads the reserved-device list from
3247c478bd9Sstevel@tonic-gate  *	the reserved-device file (which has already been opened)
3257c478bd9Sstevel@tonic-gate  *
3267c478bd9Sstevel@tonic-gate  *  Arguments:  None
3277c478bd9Sstevel@tonic-gate  *
3287c478bd9Sstevel@tonic-gate  *  Returns:  int
3297c478bd9Sstevel@tonic-gate  *	TRUE if all went well, FALSE otherwise.
3307c478bd9Sstevel@tonic-gate  *
3317c478bd9Sstevel@tonic-gate  *  Statics Used:
3327c478bd9Sstevel@tonic-gate  *	lockcount	Sets this to the number of locks in the lock list
3337c478bd9Sstevel@tonic-gate  *	locklist	Sets this to the malloc()ed space containing the
3347c478bd9Sstevel@tonic-gate  *			list of reserved devices.
3357c478bd9Sstevel@tonic-gate  *	lkfilefd	Reads data from this file
3367c478bd9Sstevel@tonic-gate  */
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate static	int
readlocks(void)3397c478bd9Sstevel@tonic-gate readlocks(void)
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate 	/* Automatics */
3427c478bd9Sstevel@tonic-gate 	struct devlks  *alloc;		/* Ptr to alloc'ed space */
3437c478bd9Sstevel@tonic-gate 	int		noerror;	/* TRUE if all is well */
3447c478bd9Sstevel@tonic-gate 	size_t		bufsiz;		/* # bytes needed for lock data */
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	/* Initializations */
3487c478bd9Sstevel@tonic-gate 	noerror = TRUE;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	/* Get the number of devices currently locked */
3517c478bd9Sstevel@tonic-gate 	if ((lockcount = getlkcnt()) > 0) {
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	    /* Allocate space for the locks */
3547c478bd9Sstevel@tonic-gate 	    bufsiz = lockcount * sizeof (struct devlks);
3557c478bd9Sstevel@tonic-gate 	    if (alloc = malloc(bufsiz)) {
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 		/* Read the locks into the malloc()ed buffer */
3587c478bd9Sstevel@tonic-gate 		if (read(lkfilefd, alloc, bufsiz) != (ssize_t)bufsiz)
3597c478bd9Sstevel@tonic-gate 		    noerror = FALSE;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 		/* If the read failed, free malloc()ed buffer */
3627c478bd9Sstevel@tonic-gate 		if (!noerror) free(alloc);
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	    } else noerror = FALSE;  /* malloc() failed */
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	} else if (lockcount < 0) noerror = FALSE;
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	/* Finished */
3697c478bd9Sstevel@tonic-gate 	if (noerror)
3707c478bd9Sstevel@tonic-gate 		locklist = (lockcount > 0) ? alloc : NULL;
3717c478bd9Sstevel@tonic-gate 	return (noerror);
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate /*
3757c478bd9Sstevel@tonic-gate  *  int getlocks()
3767c478bd9Sstevel@tonic-gate  *
3777c478bd9Sstevel@tonic-gate  *	getlocks() extracts the list of locked devices from the file
3787c478bd9Sstevel@tonic-gate  *	containing that information.  It returns the number of locked
3797c478bd9Sstevel@tonic-gate  *	devices.  If there are any locked devices, it allocates a buffer
3807c478bd9Sstevel@tonic-gate  *	for the locked file information, saves that buffer address in
3817c478bd9Sstevel@tonic-gate  *	the allocated buffer.  Also, the device lock file is open and
3827c478bd9Sstevel@tonic-gate  *	locked if the function is successful.
3837c478bd9Sstevel@tonic-gate  *
3847c478bd9Sstevel@tonic-gate  *  Arguments:  None
3857c478bd9Sstevel@tonic-gate  *
3867c478bd9Sstevel@tonic-gate  *  Returns:  int
3877c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise.  "errno" will reflect the
3887c478bd9Sstevel@tonic-gate  *	error if the function returns FALSE.
3897c478bd9Sstevel@tonic-gate  *
3907c478bd9Sstevel@tonic-gate  *  Static data referenced:
3917c478bd9Sstevel@tonic-gate  *	int lkfilefd			File descriptor of the lock file
3927c478bd9Sstevel@tonic-gate  */
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate static	int
getlocks(void)3957c478bd9Sstevel@tonic-gate getlocks(void)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate 	/* Automatic data */
3987c478bd9Sstevel@tonic-gate 	int		noerror;	/* TRUE if all's well */
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	/* Initializations */
4027c478bd9Sstevel@tonic-gate 	noerror = TRUE;
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	/* Open the lock file */
4057c478bd9Sstevel@tonic-gate 	if (_openlkfile()) {
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	    /* Lock the lock file */
4087c478bd9Sstevel@tonic-gate 	    if (locklkfile(F_WRLCK)) {
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 		/* Get the number of devices currently locked */
4117c478bd9Sstevel@tonic-gate 		if (!readlocks()) noerror = FALSE;
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 		/* If something happened, unlock the file */
4147c478bd9Sstevel@tonic-gate 		if (!noerror) (void) freelkfile();
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	    } else noerror = FALSE;  /* Lock failed */
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	    /* If something happened, close the lock file */
4197c478bd9Sstevel@tonic-gate 	    if (!noerror)
4207c478bd9Sstevel@tonic-gate 		(void) _closelkfile();
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	} else noerror = FALSE;				/* Open failed */
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	/* Done */
4257c478bd9Sstevel@tonic-gate 	return (noerror);
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate /*
4297c478bd9Sstevel@tonic-gate  *  int writelks(tblcnt)
4307c478bd9Sstevel@tonic-gate  *	int	tblcnt
4317c478bd9Sstevel@tonic-gate  *
4327c478bd9Sstevel@tonic-gate  *	writelks() writes the lock information to the lock file.  Lock
4337c478bd9Sstevel@tonic-gate  *	information includes the number of locks (to be) in the table.
4347c478bd9Sstevel@tonic-gate  *	Note that functions may still be appending new locks after this
4357c478bd9Sstevel@tonic-gate  *	call...
4367c478bd9Sstevel@tonic-gate  *
4377c478bd9Sstevel@tonic-gate  *  Arguments:
4387c478bd9Sstevel@tonic-gate  *	tblcnt	Number of locks in the lock table
4397c478bd9Sstevel@tonic-gate  *
4407c478bd9Sstevel@tonic-gate  *  Returns:
4417c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise with "errno" containing an
4427c478bd9Sstevel@tonic-gate  *	indication of the error.
4437c478bd9Sstevel@tonic-gate  *
4447c478bd9Sstevel@tonic-gate  *  Statics Used:
4457c478bd9Sstevel@tonic-gate  *	lockcount	Number of locks to exist
4467c478bd9Sstevel@tonic-gate  *	locklist	Table of locks (may not include new ones)
4477c478bd9Sstevel@tonic-gate  *	lkfilefd	File descriptor of the lock file
4487c478bd9Sstevel@tonic-gate  *
4497c478bd9Sstevel@tonic-gate  *  Notes:
4507c478bd9Sstevel@tonic-gate  *    - The number of locks that are going to be in the lock file
4517c478bd9Sstevel@tonic-gate  *	is in the static variable "lockcount".  <tblcnt> indicates
4527c478bd9Sstevel@tonic-gate  *	the number of entries in the lock table.
4537c478bd9Sstevel@tonic-gate  */
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate static	int
writelks(int tblcnt)4567c478bd9Sstevel@tonic-gate writelks(int tblcnt)
4577c478bd9Sstevel@tonic-gate {
4587c478bd9Sstevel@tonic-gate 	/* Automatic data */
4597c478bd9Sstevel@tonic-gate 	int		noerr;		/* FLAG, TRUE if all's well */
4607c478bd9Sstevel@tonic-gate 	size_t		tblsz;		/* Size of the table to write */
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	/* Initializations */
4637c478bd9Sstevel@tonic-gate 	noerr = TRUE;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	/* Rewind the OA&M Device Lock File */
466*2ed5314aSToomas Soome 	if (lseek(lkfilefd, 0L, 0) >= 0L) {
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	    /* Write the number of locks that will (eventually) exist */
4697c478bd9Sstevel@tonic-gate 	    if (write(lkfilefd, &lockcount, sizeof (int)) == sizeof (int)) {
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		/* Write the table as we currently know it */
4727c478bd9Sstevel@tonic-gate 		tblsz = tblcnt * sizeof (struct devlks);
473*2ed5314aSToomas Soome 		if (tblsz) {
474*2ed5314aSToomas Soome 		    if (write(lkfilefd, locklist, tblsz) != (ssize_t)tblsz)
4757c478bd9Sstevel@tonic-gate 			noerr = FALSE;  /* Write of locks failed */
476*2ed5314aSToomas Soome 		}
477*2ed5314aSToomas Soome 	    } else {
478*2ed5314aSToomas Soome 		noerr = FALSE;  /* write() of count failed */
479*2ed5314aSToomas Soome 	    }
480*2ed5314aSToomas Soome 	} else {
481*2ed5314aSToomas Soome 		noerr = FALSE;  /* Rewind failed */
482*2ed5314aSToomas Soome 	}
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	/* Return an indicator of our success */
4857c478bd9Sstevel@tonic-gate 	return (noerr);
4867c478bd9Sstevel@tonic-gate }
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate /*
4897c478bd9Sstevel@tonic-gate  * int appendlk(key, alias)
4907c478bd9Sstevel@tonic-gate  *	int	key
4917c478bd9Sstevel@tonic-gate  *	char   *alias
4927c478bd9Sstevel@tonic-gate  *
4937c478bd9Sstevel@tonic-gate  *	Write device locking information to the device locking file.
4947c478bd9Sstevel@tonic-gate  *
4957c478bd9Sstevel@tonic-gate  *  Arguments:
4967c478bd9Sstevel@tonic-gate  *	key	Key the device is being locked on
4977c478bd9Sstevel@tonic-gate  *	alias	The device alias being locked
4987c478bd9Sstevel@tonic-gate  *
4997c478bd9Sstevel@tonic-gate  *  Returns:  int
5007c478bd9Sstevel@tonic-gate  *	TRUE if we successfully appended a lock to the lock file,
5017c478bd9Sstevel@tonic-gate  *	FALSE with "errno" set otherwise.
5027c478bd9Sstevel@tonic-gate  *
5037c478bd9Sstevel@tonic-gate  *  Static data used:
5047c478bd9Sstevel@tonic-gate  *	lkfilefd	The open file descriptor for the open device
5057c478bd9Sstevel@tonic-gate  *			locking file
5067c478bd9Sstevel@tonic-gate  */
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate static	int
appendlk(int key,char * alias)5097c478bd9Sstevel@tonic-gate appendlk(
5107c478bd9Sstevel@tonic-gate 	int key,		/* Lock key */
5117c478bd9Sstevel@tonic-gate 	char *alias)		/* Alias to lock */
5127c478bd9Sstevel@tonic-gate {
5137c478bd9Sstevel@tonic-gate 	/* Automatic data */
5147c478bd9Sstevel@tonic-gate 	struct devlks	lk;	/* Structure for writing a lock */
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	/* Set up the data to write */
5177c478bd9Sstevel@tonic-gate 	lk.lk_key = key;
5187c478bd9Sstevel@tonic-gate 	(void) strcpy(lk.lk_alias, alias);
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	/* Write the data, returning an indicator of our success */
5217c478bd9Sstevel@tonic-gate 	return (write(lkfilefd, &lk,
5227c478bd9Sstevel@tonic-gate 	    sizeof (struct devlks)) == sizeof (struct devlks));
5237c478bd9Sstevel@tonic-gate }
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate /*
5267c478bd9Sstevel@tonic-gate  *  int compresslks()
5277c478bd9Sstevel@tonic-gate  *
5287c478bd9Sstevel@tonic-gate  *	This function compresses the lock table, squeezing out the empty
5297c478bd9Sstevel@tonic-gate  *	lock entries.
5307c478bd9Sstevel@tonic-gate  *
5317c478bd9Sstevel@tonic-gate  *  Arguments:  none
5327c478bd9Sstevel@tonic-gate  *
5337c478bd9Sstevel@tonic-gate  *  Returns:  int
5347c478bd9Sstevel@tonic-gate  *	The number of non-empty entries in the table.  They will be the
5357c478bd9Sstevel@tonic-gate  *	first 'n' entries in the table after compression.
5367c478bd9Sstevel@tonic-gate  *
5377c478bd9Sstevel@tonic-gate  *  Statics Used
5387c478bd9Sstevel@tonic-gate  *	lockcount	Number of locks in the device lock list
5397c478bd9Sstevel@tonic-gate  *	locklist	The device lock list
5407c478bd9Sstevel@tonic-gate  */
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate static	int
compresslks(void)5437c478bd9Sstevel@tonic-gate compresslks(void)
5447c478bd9Sstevel@tonic-gate {
5457c478bd9Sstevel@tonic-gate 	/* Automatics */
5467c478bd9Sstevel@tonic-gate 	struct devlks  *avail;		/* Pointer to empty slot */
5477c478bd9Sstevel@tonic-gate 	struct devlks  *p;		/* Running pointer to locks */
5487c478bd9Sstevel@tonic-gate 	int		nlocks;		/* Number of locks (up to date) */
5497c478bd9Sstevel@tonic-gate 	int		i;		/* Temporary counter */
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	/* Initializations */
5527c478bd9Sstevel@tonic-gate 	p = locklist;
5537c478bd9Sstevel@tonic-gate 	nlocks = lockcount;
5547c478bd9Sstevel@tonic-gate 	avail = NULL;
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	/* Loop through the lock list squeezing out unused slots */
5577c478bd9Sstevel@tonic-gate 	for (i = 0; i < lockcount; i++) {
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	    /* If we've found an empty slot ... */
5607c478bd9Sstevel@tonic-gate 	    if (isanullstr(p->lk_alias)) {
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 		/*
5637c478bd9Sstevel@tonic-gate 		 * If we've an empty slot to move to, just decrement
5647c478bd9Sstevel@tonic-gate 		 * count of used slots.  Otherwise, make it the next
5657c478bd9Sstevel@tonic-gate 		 * available slot
5667c478bd9Sstevel@tonic-gate 		 */
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 		nlocks--;
5697c478bd9Sstevel@tonic-gate 		if (!avail) avail = p;
5707c478bd9Sstevel@tonic-gate 	    }
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	    else if (avail) {
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 		/*
5757c478bd9Sstevel@tonic-gate 		 * If we found a slot in use and there's an
5767c478bd9Sstevel@tonic-gate 		 * available slot, move this one there
5777c478bd9Sstevel@tonic-gate 		 */
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 		(void) strcpy(avail->lk_alias, p->lk_alias);
5807c478bd9Sstevel@tonic-gate 		avail->lk_key = p->lk_key;
5817c478bd9Sstevel@tonic-gate 		avail++;
5827c478bd9Sstevel@tonic-gate 	    }
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	    /* Next, please */
5857c478bd9Sstevel@tonic-gate 	    p++;
5867c478bd9Sstevel@tonic-gate 	}
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	return (nlocks);
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate /*
5927c478bd9Sstevel@tonic-gate  *  int freelkfile()
5937c478bd9Sstevel@tonic-gate  *
5947c478bd9Sstevel@tonic-gate  *	This function unlocks the OA&M device locking file.
5957c478bd9Sstevel@tonic-gate  *
5967c478bd9Sstevel@tonic-gate  *  Arguments:  None
5977c478bd9Sstevel@tonic-gate  *
5987c478bd9Sstevel@tonic-gate  *  Returns:  int
5997c478bd9Sstevel@tonic-gate  *	TRUE if it successfully unlocked the file, FALSE otherwise
6007c478bd9Sstevel@tonic-gate  *	with "errno" set to indicate the problem.
6017c478bd9Sstevel@tonic-gate  *
6027c478bd9Sstevel@tonic-gate  *  Statics Used:
6037c478bd9Sstevel@tonic-gate  *	lkinfo		File-locking structure
6047c478bd9Sstevel@tonic-gate  *	lkfilefd	File-descriptor of the open lock file
6057c478bd9Sstevel@tonic-gate  */
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate static	int
freelkfile(void)6087c478bd9Sstevel@tonic-gate freelkfile(void)
6097c478bd9Sstevel@tonic-gate {
6107c478bd9Sstevel@tonic-gate 	/* Automatic data */
6117c478bd9Sstevel@tonic-gate 	int		noerr;		/* TRUE if all's well */
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	/* Set the action to "unlock" */
6147c478bd9Sstevel@tonic-gate 	lkinfo.l_type = F_UNLCK;
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	/* Unlock the file */
6177c478bd9Sstevel@tonic-gate 	noerr = (fcntl(lkfilefd, F_SETLK, &lkinfo) != -1);
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 	/* Return an indication of our success */
6207c478bd9Sstevel@tonic-gate 	return (noerr);
6217c478bd9Sstevel@tonic-gate }
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate /*
6247c478bd9Sstevel@tonic-gate  * int putlocks(newlist, key)
6257c478bd9Sstevel@tonic-gate  *	char  **newlist
6267c478bd9Sstevel@tonic-gate  *	int	key
6277c478bd9Sstevel@tonic-gate  *
6287c478bd9Sstevel@tonic-gate  *	This function updates the file containing OA&M device locks.
6297c478bd9Sstevel@tonic-gate  *
6307c478bd9Sstevel@tonic-gate  *  Arguments:
6317c478bd9Sstevel@tonic-gate  *	newlist		The address of the list of addresses of device
6327c478bd9Sstevel@tonic-gate  *			aliases to add to the list of locked devices
6337c478bd9Sstevel@tonic-gate  *	key		The key on which to lock the devices
6347c478bd9Sstevel@tonic-gate  *
6357c478bd9Sstevel@tonic-gate  *  Returns:  int
6367c478bd9Sstevel@tonic-gate  *	TRUE if all went well, FALSE otherwise with "errno" set to an
6377c478bd9Sstevel@tonic-gate  *	error code that indicates the problem.
6387c478bd9Sstevel@tonic-gate  *
6397c478bd9Sstevel@tonic-gate  *  Statics Used:
6407c478bd9Sstevel@tonic-gate  *	lockcount	Number of locks in the locked device structure
6417c478bd9Sstevel@tonic-gate  *	locklist	Locked device structure
6427c478bd9Sstevel@tonic-gate  */
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate static	int
putlocks(char ** newlist,int key)6457c478bd9Sstevel@tonic-gate putlocks(
6467c478bd9Sstevel@tonic-gate 	char **newlist,	/* New devices to lock */
6477c478bd9Sstevel@tonic-gate 	int key)	/* Key we're locking stuff on */
6487c478bd9Sstevel@tonic-gate {
6497c478bd9Sstevel@tonic-gate 	/* Automatic data */
6507c478bd9Sstevel@tonic-gate 	struct devlks  *plk;		/* Ptr into the locks list */
6517c478bd9Sstevel@tonic-gate 	char		**pp;		/* Pointer into the device list */
6527c478bd9Sstevel@tonic-gate 	char		**qq;		/* Another ptr into the dev list */
6537c478bd9Sstevel@tonic-gate 	int		lkndx;		/* Index into locks list */
6547c478bd9Sstevel@tonic-gate 	int		noerr;		/* TRUE if all's well */
6557c478bd9Sstevel@tonic-gate 	int		lksintbl;	/* Number of locks in the table */
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	/*
6597c478bd9Sstevel@tonic-gate 	 * Look through the existing lock list, looking for holes we can
6607c478bd9Sstevel@tonic-gate 	 * use for the newly locked devices
6617c478bd9Sstevel@tonic-gate 	 */
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	plk = locklist;
6647c478bd9Sstevel@tonic-gate 	pp = newlist;
6657c478bd9Sstevel@tonic-gate 	lkndx = 0;
6667c478bd9Sstevel@tonic-gate 	while (*pp && (lkndx < lockcount)) {
6677c478bd9Sstevel@tonic-gate 	    if (isanullstr(plk->lk_alias)) {
6687c478bd9Sstevel@tonic-gate 		plk->lk_key = key;
6697c478bd9Sstevel@tonic-gate 		(void) strcpy(plk->lk_alias, *pp++);
6707c478bd9Sstevel@tonic-gate 	    }
6717c478bd9Sstevel@tonic-gate 	    lkndx++;
6727c478bd9Sstevel@tonic-gate 	    plk++;
6737c478bd9Sstevel@tonic-gate 	}
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	/*
6767c478bd9Sstevel@tonic-gate 	 * Update the locks file (algorithm depends on whether we're adding
6777c478bd9Sstevel@tonic-gate 	 * new locks or not.  May be replacing old locks!)
6787c478bd9Sstevel@tonic-gate 	 */
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 	if (*pp) {
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	/*
6837c478bd9Sstevel@tonic-gate 	 * Need to expand the locks file
6847c478bd9Sstevel@tonic-gate 	 *  - Remember the old lock count (in existing lock buffer)
6857c478bd9Sstevel@tonic-gate 	 *  - Count the number of new locks we need to add
6867c478bd9Sstevel@tonic-gate 	 *  - Write out the old locks structure
6877c478bd9Sstevel@tonic-gate 	 *  - Append locks for the newly added locks
6887c478bd9Sstevel@tonic-gate 	 */
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	    lksintbl = lockcount;
6917c478bd9Sstevel@tonic-gate 	    for (qq = pp; *qq; qq++) lockcount++;
6927c478bd9Sstevel@tonic-gate 	    noerr = writelks(lksintbl);
6937c478bd9Sstevel@tonic-gate 	    while (noerr && *pp) noerr = appendlk(key, *pp++);
6947c478bd9Sstevel@tonic-gate 	} else {
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	/*
6977c478bd9Sstevel@tonic-gate 	 * Don't need to expand the locks file.  Compress the locks
6987c478bd9Sstevel@tonic-gate 	 * then write out the locks information
6997c478bd9Sstevel@tonic-gate 	 */
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	    lockcount = compresslks();
7027c478bd9Sstevel@tonic-gate 	    noerr = writelks(lockcount);
7037c478bd9Sstevel@tonic-gate 	}
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	/* Done.  Return an indication of our success */
7067c478bd9Sstevel@tonic-gate 	return (noerr);
7077c478bd9Sstevel@tonic-gate }
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate /*
7107c478bd9Sstevel@tonic-gate  * char *islocked(device)
7117c478bd9Sstevel@tonic-gate  *	char	       *device
7127c478bd9Sstevel@tonic-gate  *
7137c478bd9Sstevel@tonic-gate  *	This function checks a device to see if it is locked.  If it is
7147c478bd9Sstevel@tonic-gate  *	not locked, it returns the device alias.
7157c478bd9Sstevel@tonic-gate  *
7167c478bd9Sstevel@tonic-gate  *	A device is not locked if the device's alias does not appear in
7177c478bd9Sstevel@tonic-gate  *	the device locks table, or the key on which the device was locked
7187c478bd9Sstevel@tonic-gate  *	is no longer active.
7197c478bd9Sstevel@tonic-gate  *
7207c478bd9Sstevel@tonic-gate  *  Argumetns:
7217c478bd9Sstevel@tonic-gate  *	char *device		The device to be reserved.  This can be
7227c478bd9Sstevel@tonic-gate  *				a pathname to the device or a device
7237c478bd9Sstevel@tonic-gate  *				alias.
7247c478bd9Sstevel@tonic-gate  *
7257c478bd9Sstevel@tonic-gate  *  Returns:  char *
7267c478bd9Sstevel@tonic-gate  *	Returns a pointer to the device alias if it's not locked, or
7277c478bd9Sstevel@tonic-gate  *	(char *) NULL if it's locked or some error occurred.
7287c478bd9Sstevel@tonic-gate  *
7297c478bd9Sstevel@tonic-gate  *  Static data used:
7307c478bd9Sstevel@tonic-gate  *	struct devlks *locklist		Pointer to the list of device locks
7317c478bd9Sstevel@tonic-gate  *	int lockcount			The number of devices that are locked
7327c478bd9Sstevel@tonic-gate  */
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate static	char *
islocked(char * device)7357c478bd9Sstevel@tonic-gate islocked(char *device)
7367c478bd9Sstevel@tonic-gate {
7377c478bd9Sstevel@tonic-gate 	/* Automatic data */
7387c478bd9Sstevel@tonic-gate 	char		*alias;		/* Alias of "device" */
7397c478bd9Sstevel@tonic-gate 	struct devlks	*plk;		/* Ptr to locking info */
7407c478bd9Sstevel@tonic-gate 	int		locked;		/* TRUE if device in locked list */
7417c478bd9Sstevel@tonic-gate 	int		i;		/* Temp counter */
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 	/* Get the device's alias */
7447c478bd9Sstevel@tonic-gate 	if (alias = devattr(device, DTAB_ALIAS)) {
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 	/*
7477c478bd9Sstevel@tonic-gate 	 * Look through the device locks to see if this device alias
7487c478bd9Sstevel@tonic-gate 	 * is locked
7497c478bd9Sstevel@tonic-gate 	 */
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	    locked = FALSE;
7527c478bd9Sstevel@tonic-gate 	    plk = locklist;
7537c478bd9Sstevel@tonic-gate 	    for (i = 0; !locked && (i < lockcount); i++) {
7547c478bd9Sstevel@tonic-gate 		if (strncmp(alias, plk->lk_alias, DTAB_MXALIASLN) == 0)
7557c478bd9Sstevel@tonic-gate 		    locked = TRUE;
7567c478bd9Sstevel@tonic-gate 		else plk++;
7577c478bd9Sstevel@tonic-gate 	    }
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 	    if (locked) {
7607c478bd9Sstevel@tonic-gate 		    free(alias);
7617c478bd9Sstevel@tonic-gate 		    alias = NULL;
7627c478bd9Sstevel@tonic-gate 		    errno = EAGAIN;
7637c478bd9Sstevel@tonic-gate 	    }
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	}  /* devattr() failed, no such device? */
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 	/* Return pointer to the device */
7687c478bd9Sstevel@tonic-gate 	return (alias);
7697c478bd9Sstevel@tonic-gate }
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate /*
7727c478bd9Sstevel@tonic-gate  *  int unreserv(key, device)
7737c478bd9Sstevel@tonic-gate  *	int	key
7747c478bd9Sstevel@tonic-gate  *	char   *device
7757c478bd9Sstevel@tonic-gate  *
7767c478bd9Sstevel@tonic-gate  *	This function removes a device reservation.
7777c478bd9Sstevel@tonic-gate  *
7787c478bd9Sstevel@tonic-gate  *  Arguments:
7797c478bd9Sstevel@tonic-gate  *	int key	The key on which the device was allocated
7807c478bd9Sstevel@tonic-gate  *	char *device	The device to be freed.
7817c478bd9Sstevel@tonic-gate  *
7827c478bd9Sstevel@tonic-gate  *  Returns:  int
7837c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise with "errno" set.
7847c478bd9Sstevel@tonic-gate  *
7857c478bd9Sstevel@tonic-gate  *  Explicit "errno" settings:
7867c478bd9Sstevel@tonic-gate  *	(This follows the "signal()" model which gives one the ability
7877c478bd9Sstevel@tonic-gate  *	to determine if a device is allocated without having the
7887c478bd9Sstevel@tonic-gate  *	permission to free it.)
7897c478bd9Sstevel@tonic-gate  *
7907c478bd9Sstevel@tonic-gate  *	EINVAL	The device specified was not locked
7917c478bd9Sstevel@tonic-gate  *	EPERM	The device specified was locked but not on the
7927c478bd9Sstevel@tonic-gate  *		specified key
7937c478bd9Sstevel@tonic-gate  *
7947c478bd9Sstevel@tonic-gate  *  Static data used:
7957c478bd9Sstevel@tonic-gate  *	locklist	List of locked devices
7967c478bd9Sstevel@tonic-gate  *	lockcount	Number of entries in the locked-device list
7977c478bd9Sstevel@tonic-gate  */
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate int
unreserv(int key,char * device)8007c478bd9Sstevel@tonic-gate unreserv(int key, char *device)
8017c478bd9Sstevel@tonic-gate {
8027c478bd9Sstevel@tonic-gate 	/* Automatics */
8037c478bd9Sstevel@tonic-gate 	char		*srchalias;	/* Device alias to search table with */
8047c478bd9Sstevel@tonic-gate 	char		*alias;		/* Device's alias (from devattr()) */
8057c478bd9Sstevel@tonic-gate 	struct devlks	*plk;		/* Pointer to a device lock */
8067c478bd9Sstevel@tonic-gate 	int		locked;		/* TRUE if device currently locked */
8077c478bd9Sstevel@tonic-gate 	int		noerr;		/* TRUE if all's well */
8087c478bd9Sstevel@tonic-gate 	int		olderrno;	/* Entry value of "errno" */
8097c478bd9Sstevel@tonic-gate 	int		i;		/* Counter of locks */
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	/* Initializations */
8137c478bd9Sstevel@tonic-gate 	noerr = TRUE;
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 	/*
8167c478bd9Sstevel@tonic-gate 	 * Get the device alias.  If none can be found, try to free
8177c478bd9Sstevel@tonic-gate 	 * whatever it is that was given to us (the possibility exists
8187c478bd9Sstevel@tonic-gate 	 * that the device has been removed from the device table since
8197c478bd9Sstevel@tonic-gate 	 * it was reserved, so the device not being in the table shouldn't
8207c478bd9Sstevel@tonic-gate 	 * pose too much of a problem with us...)
8217c478bd9Sstevel@tonic-gate 	 */
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	olderrno = errno;
8247c478bd9Sstevel@tonic-gate 	if (alias = devattr(device, DTAB_ALIAS)) srchalias = alias;
8257c478bd9Sstevel@tonic-gate 	else {
8267c478bd9Sstevel@tonic-gate 	    errno = olderrno;
8277c478bd9Sstevel@tonic-gate 	    srchalias = device;
8287c478bd9Sstevel@tonic-gate 	}
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	/* Loop through the locked-device list looking for what we've got... */
8317c478bd9Sstevel@tonic-gate 	locked = FALSE;
8327c478bd9Sstevel@tonic-gate 	plk = locklist;
8337c478bd9Sstevel@tonic-gate 	for (i = 0; !locked && (i < lockcount); i++) {
8347c478bd9Sstevel@tonic-gate 	    if (strcmp(srchalias, plk->lk_alias) == 0)
8357c478bd9Sstevel@tonic-gate 		locked = TRUE;
8367c478bd9Sstevel@tonic-gate 	    else plk++;
8377c478bd9Sstevel@tonic-gate 	}
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 	/* Free the alias string (if any), we don't need it anymore */
8407c478bd9Sstevel@tonic-gate 	if (alias) free(alias);
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	/* If the device is locked ... */
8437c478bd9Sstevel@tonic-gate 	if (locked) {
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	/*
8467c478bd9Sstevel@tonic-gate 	 * If it's locked on the key we've been given, free it.
8477c478bd9Sstevel@tonic-gate 	 * Otherwise, don't free it and set errno to EPERM
8487c478bd9Sstevel@tonic-gate 	 */
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	    if (plk->lk_key == key) {
8517c478bd9Sstevel@tonic-gate 		plk->lk_alias[0] = '\0';
8527c478bd9Sstevel@tonic-gate 	    } else {
8537c478bd9Sstevel@tonic-gate 		noerr = FALSE;
8547c478bd9Sstevel@tonic-gate 		errno = EPERM;
8557c478bd9Sstevel@tonic-gate 	    }
8567c478bd9Sstevel@tonic-gate 	} else {
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	    /* The device isn't locked.  Set errno to EINVAL */
8597c478bd9Sstevel@tonic-gate 	    noerr = FALSE;
8607c478bd9Sstevel@tonic-gate 	    errno = EINVAL;
8617c478bd9Sstevel@tonic-gate 	}
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 	/* Finished.  Return an indication of our success */
8647c478bd9Sstevel@tonic-gate 	return (noerr);
8657c478bd9Sstevel@tonic-gate }
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate /*
8687c478bd9Sstevel@tonic-gate  *  char **devreserv(key, rsvlst)
8697c478bd9Sstevel@tonic-gate  *	int		key
8707c478bd9Sstevel@tonic-gate  *	char	      **rsvlist[]
8717c478bd9Sstevel@tonic-gate  *
8727c478bd9Sstevel@tonic-gate  *	The devreserv() function reserves devices known to the OA&M Device
8737c478bd9Sstevel@tonic-gate  *	Management family of functions.  Once a device is reserved, it can't
8747c478bd9Sstevel@tonic-gate  *	be reserved by another until it is freed or the process with the
8757c478bd9Sstevel@tonic-gate  *	"key" is no longer active.  It returns a list aliases of the devices
8767c478bd9Sstevel@tonic-gate  *	it allocated.
8777c478bd9Sstevel@tonic-gate  *
8787c478bd9Sstevel@tonic-gate  *	The function attempts to reserve a single device from each of the
8797c478bd9Sstevel@tonic-gate  *	lists.  It scans each list sequentially until it was able to
8807c478bd9Sstevel@tonic-gate  *	reserve a requested device.  If it successfully reserved a device
8817c478bd9Sstevel@tonic-gate  *	from each of the lists, it updates the device-locked file and
8827c478bd9Sstevel@tonic-gate  *	returns those aliases to the caller.  If it fails, it allocates
8837c478bd9Sstevel@tonic-gate  *	nothing and returns (char **) NULL to the caller.  "errno"
8847c478bd9Sstevel@tonic-gate  *	indicates the error.
8857c478bd9Sstevel@tonic-gate  *
8867c478bd9Sstevel@tonic-gate  *  Arguments:
8877c478bd9Sstevel@tonic-gate  *	int key			The key on which this device is being reserved.
8887c478bd9Sstevel@tonic-gate  *
8897c478bd9Sstevel@tonic-gate  *	char **rsvlist[]	The address of the list of addresses of lists
8907c478bd9Sstevel@tonic-gate  *				of pointers to the devices to allocate.
8917c478bd9Sstevel@tonic-gate  *
8927c478bd9Sstevel@tonic-gate  *  Returns:  char **
8937c478bd9Sstevel@tonic-gate  *	A pointer to malloc()ed space containing pointers to the aliases
8947c478bd9Sstevel@tonic-gate  *	of the reserved devices.  The aliases are in malloc()ed space also.
8957c478bd9Sstevel@tonic-gate  *	The list is terminated by the value (char *) NULL.
8967c478bd9Sstevel@tonic-gate  *
8977c478bd9Sstevel@tonic-gate  *  Static Data Used:
8987c478bd9Sstevel@tonic-gate  *	None directly, but functions called share hidden information
8997c478bd9Sstevel@tonic-gate  *	that really isn't of concern to devreserv().
9007c478bd9Sstevel@tonic-gate  */
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate char **
devreserv(int key,char ** rsvlst[])9037c478bd9Sstevel@tonic-gate devreserv(
9047c478bd9Sstevel@tonic-gate 	int		key,		/* Key to reserve device on */
9057c478bd9Sstevel@tonic-gate 	char		**rsvlst[])	/* List of lists of devs to reserve */
9067c478bd9Sstevel@tonic-gate {
9077c478bd9Sstevel@tonic-gate 	char		***ppp;		/* Ptr to current list in rsvlist */
9087c478bd9Sstevel@tonic-gate 	char		**pp;		/* Ptr to current item in list */
9097c478bd9Sstevel@tonic-gate 	char		**qq;		/* Ptr to item in rtnlist */
9107c478bd9Sstevel@tonic-gate 	char		**rr;		/* Ptr to item in aliases */
9117c478bd9Sstevel@tonic-gate 	char		**aliases;	/* List of aliases allocated */
9127c478bd9Sstevel@tonic-gate 	char		**rtnlist;	/* Ptr to buf to return */
9137c478bd9Sstevel@tonic-gate 	char		*alias;		/* Alias of dev to reserve */
9147c478bd9Sstevel@tonic-gate 	int		noerr;		/* TRUE if all's well */
9157c478bd9Sstevel@tonic-gate 	int		olderrno;	/* Old value of errno */
9167c478bd9Sstevel@tonic-gate 	int		gotone;		/* TRUE if unreserved dev found */
9177c478bd9Sstevel@tonic-gate 	int		foundone;	/* Found a valid device in the list */
9187c478bd9Sstevel@tonic-gate 	int		ndevs;		/* # of devs to reserve */
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	noerr = TRUE;
9217c478bd9Sstevel@tonic-gate 	ppp = rsvlst;
9227c478bd9Sstevel@tonic-gate 	olderrno = errno;
9237c478bd9Sstevel@tonic-gate 	for (ndevs = 0; *ppp++; ndevs++)
9247c478bd9Sstevel@tonic-gate 		;
9257c478bd9Sstevel@tonic-gate 	if (rtnlist = malloc((ndevs+1)*sizeof (char **))) {
9267c478bd9Sstevel@tonic-gate 	    if (aliases = malloc((ndevs+1)*sizeof (char **))) {
9277c478bd9Sstevel@tonic-gate 		if (getlocks()) {
9287c478bd9Sstevel@tonic-gate 		    qq = rtnlist;
9297c478bd9Sstevel@tonic-gate 		    rr = aliases;
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 		    /* Go through the lists of devices we're to reserve */
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 		    for (ppp = rsvlst; noerr && *ppp; ppp++) {
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 			/* Try to reserve a device from each list */
9367c478bd9Sstevel@tonic-gate 			gotone = FALSE;
9377c478bd9Sstevel@tonic-gate 			foundone = FALSE;
9387c478bd9Sstevel@tonic-gate 			for (pp = *ppp; noerr && !gotone && *pp; pp++) {
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 			/*
9417c478bd9Sstevel@tonic-gate 			 * Check the next device in the list.  If islocked()
9427c478bd9Sstevel@tonic-gate 			 * returns that device's alias, it's ours to have
9437c478bd9Sstevel@tonic-gate 			 */
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 			    if (alias = islocked(*pp)) {
9467c478bd9Sstevel@tonic-gate 				gotone = TRUE;
9477c478bd9Sstevel@tonic-gate 				foundone = TRUE;
9487c478bd9Sstevel@tonic-gate 				if (*qq = malloc(strlen(*pp)+1)) {
9497c478bd9Sstevel@tonic-gate 				    (void) strcpy(*qq++, *pp);
9507c478bd9Sstevel@tonic-gate 				    *rr++ = alias;
9517c478bd9Sstevel@tonic-gate 				} else {
9527c478bd9Sstevel@tonic-gate 				    *rr = NULL;
9537c478bd9Sstevel@tonic-gate 				    noerr = FALSE;
9547c478bd9Sstevel@tonic-gate 				}
9557c478bd9Sstevel@tonic-gate 			    } else {
9567c478bd9Sstevel@tonic-gate 				if (errno == EAGAIN) {
9577c478bd9Sstevel@tonic-gate 				    foundone = TRUE;
9587c478bd9Sstevel@tonic-gate 				    errno = olderrno;
9597c478bd9Sstevel@tonic-gate 				} else if (errno == ENODEV) errno = olderrno;
9607c478bd9Sstevel@tonic-gate 				else {
9617c478bd9Sstevel@tonic-gate 				    noerr = FALSE;
9627c478bd9Sstevel@tonic-gate 				    *rr = NULL;
9637c478bd9Sstevel@tonic-gate 				}
9647c478bd9Sstevel@tonic-gate 			    }
9657c478bd9Sstevel@tonic-gate 			}
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 			/*
9687c478bd9Sstevel@tonic-gate 			 * If no device from the list could be reserved,
9697c478bd9Sstevel@tonic-gate 			 * we've failed
9707c478bd9Sstevel@tonic-gate 			 */
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 			if (noerr && !gotone) {
9737c478bd9Sstevel@tonic-gate 			    noerr = FALSE;
9747c478bd9Sstevel@tonic-gate 			    if (!foundone) errno = ENODEV;
9757c478bd9Sstevel@tonic-gate 			    else errno = EAGAIN;
9767c478bd9Sstevel@tonic-gate 			    *qq = NULL;
9777c478bd9Sstevel@tonic-gate 			    *rr = NULL;
9787c478bd9Sstevel@tonic-gate 			}
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 		    } /* End of loop through lists loop */
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 		/*
9837c478bd9Sstevel@tonic-gate 		 * If all went well, update lock file.
9847c478bd9Sstevel@tonic-gate 		 * Then, free locks
9857c478bd9Sstevel@tonic-gate 		 */
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 		    if (noerr) {
9887c478bd9Sstevel@tonic-gate 			*qq = NULL;
9897c478bd9Sstevel@tonic-gate 			*rr = NULL;
9907c478bd9Sstevel@tonic-gate 			if (!putlocks(aliases, key)) noerr = FALSE;
9917c478bd9Sstevel@tonic-gate 		    }
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 		    /* Free resources */
9947c478bd9Sstevel@tonic-gate 		    if (!freelkfile()) noerr = FALSE;
9957c478bd9Sstevel@tonic-gate 		    if (_closelkfile() != 0) noerr = FALSE;
9967c478bd9Sstevel@tonic-gate 		    for (qq = aliases; *qq; qq++) free(*qq);
9977c478bd9Sstevel@tonic-gate 		    if (!noerr)
9987c478bd9Sstevel@tonic-gate 			for (pp = rtnlist; *pp; pp++)
9997c478bd9Sstevel@tonic-gate 				free(*pp);
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 		} else noerr = FALSE; /* Error getting locks */
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 		free(aliases);
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;  /* Malloc() for alias list failed */
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	    if (!noerr) {
10087c478bd9Sstevel@tonic-gate 		free(rtnlist);
10097c478bd9Sstevel@tonic-gate 		rtnlist = NULL;
10107c478bd9Sstevel@tonic-gate 	    }
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;  /* malloc() failed */
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 	/* Return list or an indication of an error */
10157c478bd9Sstevel@tonic-gate 	return (noerr ? rtnlist : NULL);
10167c478bd9Sstevel@tonic-gate }
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate /*
10197c478bd9Sstevel@tonic-gate  *  int devfree(key, device)
10207c478bd9Sstevel@tonic-gate  *	int	key
10217c478bd9Sstevel@tonic-gate  *	char   *device
10227c478bd9Sstevel@tonic-gate  *
10237c478bd9Sstevel@tonic-gate  *	This function unreserves (frees) the given device.  It returns
10247c478bd9Sstevel@tonic-gate  *	an indication of success with "errno" containing information about
10257c478bd9Sstevel@tonic-gate  *	a failure.
10267c478bd9Sstevel@tonic-gate  *
10277c478bd9Sstevel@tonic-gate  *  Arguments:
10287c478bd9Sstevel@tonic-gate  *	int	key	The key that the device is locked on
10297c478bd9Sstevel@tonic-gate  *	char   *device	The device (alias, pathname to, etc.) to be freed.
10307c478bd9Sstevel@tonic-gate  *
10317c478bd9Sstevel@tonic-gate  *  Returns:  int
10327c478bd9Sstevel@tonic-gate  *	0 if successful, -1 with "errno" set if fails.
10337c478bd9Sstevel@tonic-gate  */
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate int
devfree(int key,char * device)10367c478bd9Sstevel@tonic-gate devfree(
10377c478bd9Sstevel@tonic-gate 	int	key,			/* Key device is locked on */
10387c478bd9Sstevel@tonic-gate 	char   *device)			/* Device to free */
10397c478bd9Sstevel@tonic-gate {
10407c478bd9Sstevel@tonic-gate 	/* Automatics */
10417c478bd9Sstevel@tonic-gate 	int	noerr;
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	/* Initializations */
10447c478bd9Sstevel@tonic-gate 	noerr = TRUE;
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate 	/* Get the locks, locking the lock file */
10477c478bd9Sstevel@tonic-gate 	if (getlocks()) {
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 	    /* Attempt to unreserve the device */
10507c478bd9Sstevel@tonic-gate 	    if (unreserv(key, device)) {
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 		/*
10537c478bd9Sstevel@tonic-gate 		 * Successful.  Compress the lock structure and
10547c478bd9Sstevel@tonic-gate 		 * write the new locks
10557c478bd9Sstevel@tonic-gate 		 */
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 		lockcount = compresslks();
10587c478bd9Sstevel@tonic-gate 		if (!writelks(lockcount)) noerr = FALSE;
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;  /* Couldn't unreserve the device */
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 	    /* Unlock and close the locks file */
10637c478bd9Sstevel@tonic-gate 	    if (!freelkfile()) noerr = FALSE;
10647c478bd9Sstevel@tonic-gate 	    if (_closelkfile() != 0) noerr = FALSE;
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 	/* Return 0 if successful, something else otherwise */
10697c478bd9Sstevel@tonic-gate 	return (noerr? 0 : -1);
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate /*
10737c478bd9Sstevel@tonic-gate  *  struct reservdev **reservdev()
10747c478bd9Sstevel@tonic-gate  *
10757c478bd9Sstevel@tonic-gate  *	This function returns the list of reserved devices
10767c478bd9Sstevel@tonic-gate  *	along with the key on which those devices were locked.
10777c478bd9Sstevel@tonic-gate  *
10787c478bd9Sstevel@tonic-gate  *  Arguments:  None.
10797c478bd9Sstevel@tonic-gate  *
10807c478bd9Sstevel@tonic-gate  *  Returns:  struct reservdev **
10817c478bd9Sstevel@tonic-gate  *	Pointer to the list of pointers to structures describing
10827c478bd9Sstevel@tonic-gate  *	the reserved devices, or (struct reservdev **) NULL if an
10837c478bd9Sstevel@tonic-gate  *	error occurred.  The list of pointers is terminated by
10847c478bd9Sstevel@tonic-gate  *	(struct reservdev *) NULL.
10857c478bd9Sstevel@tonic-gate  *
10867c478bd9Sstevel@tonic-gate  *  Statics Used:
10877c478bd9Sstevel@tonic-gate  *	locklist	List of reserved devices
10887c478bd9Sstevel@tonic-gate  *	lockcount	Number of items in the reserved-devices list
10897c478bd9Sstevel@tonic-gate  */
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate struct reservdev **
reservdev(void)10927c478bd9Sstevel@tonic-gate reservdev(void)
10937c478bd9Sstevel@tonic-gate {
10947c478bd9Sstevel@tonic-gate 	/* Automatics */
10957c478bd9Sstevel@tonic-gate 	struct reservdev	**rtnlist;	/* Ptr to return list */
10967c478bd9Sstevel@tonic-gate 	struct devlks		*p;		/* Running ptr, locklist */
10977c478bd9Sstevel@tonic-gate 	struct reservdev	**q;		/* Running ptr, rtnlist */
10987c478bd9Sstevel@tonic-gate 	char			*r;		/* Temp ptr to char */
10997c478bd9Sstevel@tonic-gate 	size_t			bufsiz;		/* Size of buffer to alloc */
11007c478bd9Sstevel@tonic-gate 	int			noerr;		/* TRUE if all's well */
11017c478bd9Sstevel@tonic-gate 	int			i;		/* Lock counter */
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 	/* Initializations */
11057c478bd9Sstevel@tonic-gate 	noerr = TRUE;
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	/* Open the lock file ... */
11087c478bd9Sstevel@tonic-gate 	if (_openlkfile()) {
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 	    /* Put a read-lock on the lock-file ... */
11117c478bd9Sstevel@tonic-gate 	    if (locklkfile(F_RDLCK)) {
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 		/* Read the locks ... */
11147c478bd9Sstevel@tonic-gate 		if (readlocks()) {
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 		    /* Alloc space for the return list */
11177c478bd9Sstevel@tonic-gate 		    bufsiz = (lockcount+1) * sizeof (struct reservdev *);
11187c478bd9Sstevel@tonic-gate 		    if (rtnlist = malloc(bufsiz)) {
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 			/* Build the return list from the lock list */
11217c478bd9Sstevel@tonic-gate 			p = locklist;
11227c478bd9Sstevel@tonic-gate 			q = rtnlist;
11237c478bd9Sstevel@tonic-gate 			for (i = 0; noerr && (i < lockcount); i++) {
11247c478bd9Sstevel@tonic-gate 			    if (*q = malloc(sizeof (struct reservdev))) {
11257c478bd9Sstevel@tonic-gate 				if (r = malloc(strlen(p->lk_alias)+1)) {
11267c478bd9Sstevel@tonic-gate 				    (*q)->devname = strcpy(r, p->lk_alias);
11277c478bd9Sstevel@tonic-gate 				    (*q)->key = p->lk_key;
11287c478bd9Sstevel@tonic-gate 				} else noerr = FALSE;  /* malloc() error */
11297c478bd9Sstevel@tonic-gate 			    } else noerr = FALSE;  /* malloc() error */
11307c478bd9Sstevel@tonic-gate 			    p++;
11317c478bd9Sstevel@tonic-gate 			    q++;
11327c478bd9Sstevel@tonic-gate 			}
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 			/*
11357c478bd9Sstevel@tonic-gate 			 * If no error, terminate the list.  Otherwise, free
11367c478bd9Sstevel@tonic-gate 			 * the space we've allocated
11377c478bd9Sstevel@tonic-gate 			 */
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 			if (noerr) *q = NULL;
11407c478bd9Sstevel@tonic-gate 			else {
11417c478bd9Sstevel@tonic-gate 			    for (q = rtnlist; *q; q++) {
11427c478bd9Sstevel@tonic-gate 				free((*q)->devname);
11437c478bd9Sstevel@tonic-gate 				free(*q);
11447c478bd9Sstevel@tonic-gate 			    }
11457c478bd9Sstevel@tonic-gate 			    free(rtnlist);
11467c478bd9Sstevel@tonic-gate 			}
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate 		    } else noerr = FALSE;  /* Couldn't malloc() list space */
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 		} else noerr = FALSE;  /* Problem reading locks */
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 		/* Free the lock file */
11537c478bd9Sstevel@tonic-gate 		(void) freelkfile();
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;  /* Error locking the lock file */
11567c478bd9Sstevel@tonic-gate 
11577c478bd9Sstevel@tonic-gate 	    /* Close the lock file */
11587c478bd9Sstevel@tonic-gate 	    (void) _closelkfile();
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;  /* Error opening the lock file */
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	/* Return ptr to list of locks or NULL if an error has occurred */
11637c478bd9Sstevel@tonic-gate 	return (noerr ? rtnlist : NULL);
11647c478bd9Sstevel@tonic-gate }
1165