xref: /titanic_41/usr/src/lib/libadm/common/devreserv.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1997, by Sun Microsystems, Inc.
28*7c478bd9Sstevel@tonic-gate  * All rights reserved.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate /*
35*7c478bd9Sstevel@tonic-gate  * Globals defined:
36*7c478bd9Sstevel@tonic-gate  *
37*7c478bd9Sstevel@tonic-gate  *	devreserv()	Reserve a set of OA&M devices
38*7c478bd9Sstevel@tonic-gate  *	devfree()	Free a reserved device
39*7c478bd9Sstevel@tonic-gate  *	reservdev()	Get a list of reserved devices
40*7c478bd9Sstevel@tonic-gate  *	_openlkfile()	Opens the lock file
41*7c478bd9Sstevel@tonic-gate  *	_rsvtabpath()	Get the pathname of the lock table file
42*7c478bd9Sstevel@tonic-gate  *	_closelkfile()	Closes the lock file
43*7c478bd9Sstevel@tonic-gate  */
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate /*
46*7c478bd9Sstevel@tonic-gate  * Headers referenced:
47*7c478bd9Sstevel@tonic-gate  *	<sys/types.h>	System data types
48*7c478bd9Sstevel@tonic-gate  *	<errno.h>	Error definitions (including "errno")
49*7c478bd9Sstevel@tonic-gate  *	<string.h>	String handling definitions
50*7c478bd9Sstevel@tonic-gate  *	<fcntl.h>	File control definitions
51*7c478bd9Sstevel@tonic-gate  *	<unistd.h>	Unix standard value definitions
52*7c478bd9Sstevel@tonic-gate  *	<devmgmt.h>	Global Device Management definitions
53*7c478bd9Sstevel@tonic-gate  *	"devtab.h"	Local Device Management definitions
54*7c478bd9Sstevel@tonic-gate  */
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate #include	<sys/types.h>
57*7c478bd9Sstevel@tonic-gate #include	<errno.h>
58*7c478bd9Sstevel@tonic-gate #include	<string.h>
59*7c478bd9Sstevel@tonic-gate #include	<fcntl.h>
60*7c478bd9Sstevel@tonic-gate #include	<unistd.h>
61*7c478bd9Sstevel@tonic-gate #include	<stdlib.h>
62*7c478bd9Sstevel@tonic-gate #include	<devmgmt.h>
63*7c478bd9Sstevel@tonic-gate #include	"devtab.h"
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate /*
66*7c478bd9Sstevel@tonic-gate  * Local Definitions:
67*7c478bd9Sstevel@tonic-gate  */
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate /*
71*7c478bd9Sstevel@tonic-gate  * Local data types:
72*7c478bd9Sstevel@tonic-gate  *	struct devlks	Structure that defines locking information (key
73*7c478bd9Sstevel@tonic-gate  *			with alias name (may be '\0' terminated)
74*7c478bd9Sstevel@tonic-gate  */
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate struct devlks {
77*7c478bd9Sstevel@tonic-gate 	int	lk_key;
78*7c478bd9Sstevel@tonic-gate 	char	lk_alias[((DTAB_MXALIASLN+2)/2)*2];
79*7c478bd9Sstevel@tonic-gate };
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate /*
83*7c478bd9Sstevel@tonic-gate  * Local Functions:
84*7c478bd9Sstevel@tonic-gate  *	isanullstr()	Is a character string a null string ("")?
85*7c478bd9Sstevel@tonic-gate  *	getlkcnt()	Get the number of devices locked
86*7c478bd9Sstevel@tonic-gate  *	locklkfile()	Lock the OA&M Device locking file
87*7c478bd9Sstevel@tonic-gate  *	getlocks()	Get the device locks from the device-lock file
88*7c478bd9Sstevel@tonic-gate  *	islocked()	Determines if a device is locked
89*7c478bd9Sstevel@tonic-gate  *	putlocks()	Close the device locks w/ update
90*7c478bd9Sstevel@tonic-gate  *	freelkfile()	Close the device locks w/o updating
91*7c478bd9Sstevel@tonic-gate  *	compresslks()	Compresses the table containing lock info
92*7c478bd9Sstevel@tonic-gate  */
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate #define	isanullstr(s)	(s[0] == '\0')
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate static	int	locklkfile(short);	/* Lock the lock file */
97*7c478bd9Sstevel@tonic-gate static	int	getlkcnt(void);		/* Get the number of locked devices */
98*7c478bd9Sstevel@tonic-gate static	int	getlocks(void);		/* Get the lock information */
99*7c478bd9Sstevel@tonic-gate static	int	putlocks(char **, int); /* Update lock information */
100*7c478bd9Sstevel@tonic-gate static	int	freelkfile(void);	/* Free lock information (no update) */
101*7c478bd9Sstevel@tonic-gate static	char   *islocked(char *);	/* Determines if a device is locked */
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate /*
105*7c478bd9Sstevel@tonic-gate  * Static data
106*7c478bd9Sstevel@tonic-gate  */
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate static	struct flock	lkinfo = {0, 0, 0, 0, 0};
109*7c478bd9Sstevel@tonic-gate static	struct devlks  *locklist;
110*7c478bd9Sstevel@tonic-gate static	int		lockcount;
111*7c478bd9Sstevel@tonic-gate static	int		lkfilefd = -1;
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate /*
114*7c478bd9Sstevel@tonic-gate  * char *_rsvtabpath()
115*7c478bd9Sstevel@tonic-gate  *
116*7c478bd9Sstevel@tonic-gate  *	Determines the pathname of the device reservation table file
117*7c478bd9Sstevel@tonic-gate  *
118*7c478bd9Sstevel@tonic-gate  *	Uses the following sequential steps:
119*7c478bd9Sstevel@tonic-gate  *	     1)	If OAM_DEVLKFILE is defined and is not null, use that as
120*7c478bd9Sstevel@tonic-gate  *		the pathname to the file
121*7c478bd9Sstevel@tonic-gate  *	     2)	Otherwise, use the devault name found in DVLK_PATH (defined
122*7c478bd9Sstevel@tonic-gate  *		in the header file <devtab.h>
123*7c478bd9Sstevel@tonic-gate  *
124*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
125*7c478bd9Sstevel@tonic-gate  *
126*7c478bd9Sstevel@tonic-gate  *  Returns:  char *
127*7c478bd9Sstevel@tonic-gate  *	A pointer to the filename in malloc()ed memory or (char *) NULL if
128*7c478bd9Sstevel@tonic-gate  *	it fails.  "errno" will indicate the error if it fails.
129*7c478bd9Sstevel@tonic-gate  */
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate char *
_rsvtabpath(void)132*7c478bd9Sstevel@tonic-gate _rsvtabpath(void)
133*7c478bd9Sstevel@tonic-gate {
134*7c478bd9Sstevel@tonic-gate 	/* Automatics */
135*7c478bd9Sstevel@tonic-gate 	char		*lockname;	/* Name of the lockfile */
136*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
137*7c478bd9Sstevel@tonic-gate 	char		*p;		/* Temporary pointer */
138*7c478bd9Sstevel@tonic-gate #endif
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
141*7c478bd9Sstevel@tonic-gate 	p = getenv(OAM_DEVLKTAB);
142*7c478bd9Sstevel@tonic-gate 	if ((p != NULL) && (*p != '\0')) {
143*7c478bd9Sstevel@tonic-gate 	    if (lockname = malloc(strlen(p)+1))
144*7c478bd9Sstevel@tonic-gate 		(void) strcpy(lockname, p);
145*7c478bd9Sstevel@tonic-gate 	} else {
146*7c478bd9Sstevel@tonic-gate #endif
147*7c478bd9Sstevel@tonic-gate 	    if (lockname = malloc(strlen(DVLK_PATH)+1))
148*7c478bd9Sstevel@tonic-gate 		(void) strcpy(lockname, DVLK_PATH);
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
151*7c478bd9Sstevel@tonic-gate 	}
152*7c478bd9Sstevel@tonic-gate #endif
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	/* Fini -- return a pointer to the lockfile pathname */
155*7c478bd9Sstevel@tonic-gate 	return (lockname);
156*7c478bd9Sstevel@tonic-gate }
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate /*
159*7c478bd9Sstevel@tonic-gate  *  int _openlkfile()
160*7c478bd9Sstevel@tonic-gate  *
161*7c478bd9Sstevel@tonic-gate  *	The _openlkfile() function opens a device-reservation table file
162*7c478bd9Sstevel@tonic-gate  *	for read/write access.
163*7c478bd9Sstevel@tonic-gate  *
164*7c478bd9Sstevel@tonic-gate  *  Arguments: None
165*7c478bd9Sstevel@tonic-gate  *
166*7c478bd9Sstevel@tonic-gate  *  Returns:  int
167*7c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise.
168*7c478bd9Sstevel@tonic-gate  *
169*7c478bd9Sstevel@tonic-gate  *  Statics Used:
170*7c478bd9Sstevel@tonic-gate  *	lkfilefd	Lock file file descriptor
171*7c478bd9Sstevel@tonic-gate  */
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate int
_openlkfile(void)174*7c478bd9Sstevel@tonic-gate _openlkfile(void)
175*7c478bd9Sstevel@tonic-gate {
176*7c478bd9Sstevel@tonic-gate 	/*
177*7c478bd9Sstevel@tonic-gate 	 *  Automatic data
178*7c478bd9Sstevel@tonic-gate 	 */
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	char   *lockname;		/* Name of the lock file */
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	/* Close the lockfile -- it might be open */
184*7c478bd9Sstevel@tonic-gate 	(void) _closelkfile();
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate 	/* If we can get the name of the lock file ... */
187*7c478bd9Sstevel@tonic-gate 	if (lockname = _rsvtabpath()) {
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	    /* Open it */
190*7c478bd9Sstevel@tonic-gate 	    lkfilefd = open(lockname, O_RDWR|O_CREAT, 0600);
191*7c478bd9Sstevel@tonic-gate 	    free(lockname);
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	}
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	/*  Finis  */
196*7c478bd9Sstevel@tonic-gate 	return ((lkfilefd != -1) ? TRUE : FALSE);
197*7c478bd9Sstevel@tonic-gate }
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate /*
200*7c478bd9Sstevel@tonic-gate  * int _closelkfile()
201*7c478bd9Sstevel@tonic-gate  *
202*7c478bd9Sstevel@tonic-gate  *	Function closes the device-reservation table file and sets the
203*7c478bd9Sstevel@tonic-gate  *	necessary external variables to indicate such.
204*7c478bd9Sstevel@tonic-gate  *
205*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
206*7c478bd9Sstevel@tonic-gate  *
207*7c478bd9Sstevel@tonic-gate  *  Returns:  int
208*7c478bd9Sstevel@tonic-gate  *	Same as close()
209*7c478bd9Sstevel@tonic-gate  *
210*7c478bd9Sstevel@tonic-gate  *  Statics referenced:
211*7c478bd9Sstevel@tonic-gate  *	lkfilefd	The device reservation table file's file descriptor
212*7c478bd9Sstevel@tonic-gate  */
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate int
_closelkfile(void)215*7c478bd9Sstevel@tonic-gate _closelkfile(void)
216*7c478bd9Sstevel@tonic-gate {
217*7c478bd9Sstevel@tonic-gate 	/* Automatics */
218*7c478bd9Sstevel@tonic-gate 	int	rtnval;		/* Value to return */
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	/* Close the lock file if it's open */
221*7c478bd9Sstevel@tonic-gate 	if (lkfilefd != -1) rtnval = close(lkfilefd);
222*7c478bd9Sstevel@tonic-gate 	else rtnval = 0;
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 	/* Indicate that the lock-file is closed */
225*7c478bd9Sstevel@tonic-gate 	lkfilefd = -1;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	/* Finis */
228*7c478bd9Sstevel@tonic-gate 	return (rtnval);
229*7c478bd9Sstevel@tonic-gate }
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate /*
232*7c478bd9Sstevel@tonic-gate  *  int locklkfile(lkflag)
233*7c478bd9Sstevel@tonic-gate  *	short		lkflag
234*7c478bd9Sstevel@tonic-gate  *
235*7c478bd9Sstevel@tonic-gate  *	This function locks the device lock file.  If the request cannot
236*7c478bd9Sstevel@tonic-gate  *	be serviced, it keeps on trying until it manages to lock the file
237*7c478bd9Sstevel@tonic-gate  *	or it encounters an error.
238*7c478bd9Sstevel@tonic-gate  *
239*7c478bd9Sstevel@tonic-gate  *  Arguments:
240*7c478bd9Sstevel@tonic-gate  *	lkflag		Flag (from FCNTL(BA_OS)) indicating which type
241*7c478bd9Sstevel@tonic-gate  *			of lock is being requested.  Values that make
242*7c478bd9Sstevel@tonic-gate  *			sense:
243*7c478bd9Sstevel@tonic-gate  *				F_RDLCK:	Read lock.
244*7c478bd9Sstevel@tonic-gate  *				F_WRLCK:	Write lock.
245*7c478bd9Sstevel@tonic-gate  *
246*7c478bd9Sstevel@tonic-gate  *  Returns: int
247*7c478bd9Sstevel@tonic-gate  *	TRUE (non-zero) if the function managed to lock the file, FALSE
248*7c478bd9Sstevel@tonic-gate  *	otherwise ("errno" will indicate the problem).
249*7c478bd9Sstevel@tonic-gate  *
250*7c478bd9Sstevel@tonic-gate  *  Statics used:
251*7c478bd9Sstevel@tonic-gate  *	int lkfilefd		File descriptor of the open lock file
252*7c478bd9Sstevel@tonic-gate  *	struct flock lkinfo	Structure used by fcntl() to lock a file
253*7c478bd9Sstevel@tonic-gate  */
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate static	int
locklkfile(short lkflag)256*7c478bd9Sstevel@tonic-gate locklkfile(short lkflag)
257*7c478bd9Sstevel@tonic-gate {
258*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
259*7c478bd9Sstevel@tonic-gate 	int		noerror;	/* TRUE if no error yet */
260*7c478bd9Sstevel@tonic-gate 	int		locked;		/* TRUE if the file is locked */
261*7c478bd9Sstevel@tonic-gate 	int		olderrno;	/* Value of errno on call */
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 	/* Set up the locking structure */
265*7c478bd9Sstevel@tonic-gate 	lkinfo.l_type = lkflag;
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 	/* Try to lock the file.  If it's locked, wait and try again */
268*7c478bd9Sstevel@tonic-gate 	noerror = TRUE;
269*7c478bd9Sstevel@tonic-gate 	locked = FALSE;
270*7c478bd9Sstevel@tonic-gate 	olderrno = errno;
271*7c478bd9Sstevel@tonic-gate 	while (noerror && !locked) {
272*7c478bd9Sstevel@tonic-gate 	    if (fcntl(lkfilefd, F_SETLK, &lkinfo) != -1) locked = TRUE;
273*7c478bd9Sstevel@tonic-gate 	    else {
274*7c478bd9Sstevel@tonic-gate 		if ((errno == EACCES) || (errno == EAGAIN)) {
275*7c478bd9Sstevel@tonic-gate 		    errno = olderrno;
276*7c478bd9Sstevel@tonic-gate 		    if (sleep(2)) noerror = FALSE;
277*7c478bd9Sstevel@tonic-gate 		} else noerror = FALSE;
278*7c478bd9Sstevel@tonic-gate 	    }
279*7c478bd9Sstevel@tonic-gate 	}
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	/* Return a success flag */
282*7c478bd9Sstevel@tonic-gate 	return (locked);
283*7c478bd9Sstevel@tonic-gate }
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate /*
286*7c478bd9Sstevel@tonic-gate  *  int getlkcnt()
287*7c478bd9Sstevel@tonic-gate  *
288*7c478bd9Sstevel@tonic-gate  *	This function extracts the number of currently-locked devices
289*7c478bd9Sstevel@tonic-gate  *	from the lock file.
290*7c478bd9Sstevel@tonic-gate  *
291*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
292*7c478bd9Sstevel@tonic-gate  *
293*7c478bd9Sstevel@tonic-gate  *  Returns:  int
294*7c478bd9Sstevel@tonic-gate  *	The number of devices locked or -1 if an error occurred.
295*7c478bd9Sstevel@tonic-gate  *
296*7c478bd9Sstevel@tonic-gate  *  Statics used:
297*7c478bd9Sstevel@tonic-gate  *	lkfilefd	File descriptor of the open lockfile
298*7c478bd9Sstevel@tonic-gate  *
299*7c478bd9Sstevel@tonic-gate  *  Assumptions:
300*7c478bd9Sstevel@tonic-gate  *    -	The file is positioned to the beginning-of-file
301*7c478bd9Sstevel@tonic-gate  */
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate static	int
getlkcnt(void)304*7c478bd9Sstevel@tonic-gate getlkcnt(void)
305*7c478bd9Sstevel@tonic-gate {
306*7c478bd9Sstevel@tonic-gate 	/* Automatics */
307*7c478bd9Sstevel@tonic-gate 	int	cntread;		/* Number of bytes read */
308*7c478bd9Sstevel@tonic-gate 	int	lkcnt;			/* Number of current locks */
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	/* Get the lock count from the file */
311*7c478bd9Sstevel@tonic-gate 	cntread = (int)read(lkfilefd, &lkcnt, sizeof (int));
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	/* If there wasn't one, set to 0.  If error, set to -1 */
314*7c478bd9Sstevel@tonic-gate 	if (cntread != (int)sizeof (int))
315*7c478bd9Sstevel@tonic-gate 		lkcnt = (cntread < 0) ? -1 : 0;
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	/* Return the lock count */
318*7c478bd9Sstevel@tonic-gate 	return (lkcnt);
319*7c478bd9Sstevel@tonic-gate }
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate /*
322*7c478bd9Sstevel@tonic-gate  *  int readlocks()
323*7c478bd9Sstevel@tonic-gate  *
324*7c478bd9Sstevel@tonic-gate  *	The readlocks() function reads the reserved-device list from
325*7c478bd9Sstevel@tonic-gate  *	the reserved-device file (which has already been opened)
326*7c478bd9Sstevel@tonic-gate  *
327*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
328*7c478bd9Sstevel@tonic-gate  *
329*7c478bd9Sstevel@tonic-gate  *  Returns:  int
330*7c478bd9Sstevel@tonic-gate  *	TRUE if all went well, FALSE otherwise.
331*7c478bd9Sstevel@tonic-gate  *
332*7c478bd9Sstevel@tonic-gate  *  Statics Used:
333*7c478bd9Sstevel@tonic-gate  *	lockcount	Sets this to the number of locks in the lock list
334*7c478bd9Sstevel@tonic-gate  *	locklist	Sets this to the malloc()ed space containing the
335*7c478bd9Sstevel@tonic-gate  *			list of reserved devices.
336*7c478bd9Sstevel@tonic-gate  *	lkfilefd	Reads data from this file
337*7c478bd9Sstevel@tonic-gate  */
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate static	int
readlocks(void)340*7c478bd9Sstevel@tonic-gate readlocks(void)
341*7c478bd9Sstevel@tonic-gate {
342*7c478bd9Sstevel@tonic-gate 	/* Automatics */
343*7c478bd9Sstevel@tonic-gate 	struct devlks  *alloc;		/* Ptr to alloc'ed space */
344*7c478bd9Sstevel@tonic-gate 	int		noerror;	/* TRUE if all is well */
345*7c478bd9Sstevel@tonic-gate 	size_t		bufsiz;		/* # bytes needed for lock data */
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 	/* Initializations */
349*7c478bd9Sstevel@tonic-gate 	noerror = TRUE;
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 	/* Get the number of devices currently locked */
352*7c478bd9Sstevel@tonic-gate 	if ((lockcount = getlkcnt()) > 0) {
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate 	    /* Allocate space for the locks */
355*7c478bd9Sstevel@tonic-gate 	    bufsiz = lockcount * sizeof (struct devlks);
356*7c478bd9Sstevel@tonic-gate 	    if (alloc = malloc(bufsiz)) {
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 		/* Read the locks into the malloc()ed buffer */
359*7c478bd9Sstevel@tonic-gate 		if (read(lkfilefd, alloc, bufsiz) != (ssize_t)bufsiz)
360*7c478bd9Sstevel@tonic-gate 		    noerror = FALSE;
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 		/* If the read failed, free malloc()ed buffer */
363*7c478bd9Sstevel@tonic-gate 		if (!noerror) free(alloc);
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	    } else noerror = FALSE;  /* malloc() failed */
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate 	} else if (lockcount < 0) noerror = FALSE;
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 	/* Finished */
370*7c478bd9Sstevel@tonic-gate 	if (noerror)
371*7c478bd9Sstevel@tonic-gate 		locklist = (lockcount > 0) ? alloc : NULL;
372*7c478bd9Sstevel@tonic-gate 	return (noerror);
373*7c478bd9Sstevel@tonic-gate }
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate /*
376*7c478bd9Sstevel@tonic-gate  *  int getlocks()
377*7c478bd9Sstevel@tonic-gate  *
378*7c478bd9Sstevel@tonic-gate  *	getlocks() extracts the list of locked devices from the file
379*7c478bd9Sstevel@tonic-gate  *	containing that information.  It returns the number of locked
380*7c478bd9Sstevel@tonic-gate  *	devices.  If there are any locked devices, it allocates a buffer
381*7c478bd9Sstevel@tonic-gate  *	for the locked file information, saves that buffer address in
382*7c478bd9Sstevel@tonic-gate  *	the allocated buffer.  Also, the device lock file is open and
383*7c478bd9Sstevel@tonic-gate  *	locked if the function is successful.
384*7c478bd9Sstevel@tonic-gate  *
385*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
386*7c478bd9Sstevel@tonic-gate  *
387*7c478bd9Sstevel@tonic-gate  *  Returns:  int
388*7c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise.  "errno" will reflect the
389*7c478bd9Sstevel@tonic-gate  *	error if the function returns FALSE.
390*7c478bd9Sstevel@tonic-gate  *
391*7c478bd9Sstevel@tonic-gate  *  Static data referenced:
392*7c478bd9Sstevel@tonic-gate  *	int lkfilefd			File descriptor of the lock file
393*7c478bd9Sstevel@tonic-gate  */
394*7c478bd9Sstevel@tonic-gate 
395*7c478bd9Sstevel@tonic-gate static	int
getlocks(void)396*7c478bd9Sstevel@tonic-gate getlocks(void)
397*7c478bd9Sstevel@tonic-gate {
398*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
399*7c478bd9Sstevel@tonic-gate 	int		noerror;	/* TRUE if all's well */
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	/* Initializations */
403*7c478bd9Sstevel@tonic-gate 	noerror = TRUE;
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 	/* Open the lock file */
406*7c478bd9Sstevel@tonic-gate 	if (_openlkfile()) {
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 	    /* Lock the lock file */
409*7c478bd9Sstevel@tonic-gate 	    if (locklkfile(F_WRLCK)) {
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 		/* Get the number of devices currently locked */
412*7c478bd9Sstevel@tonic-gate 		if (!readlocks()) noerror = FALSE;
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 		/* If something happened, unlock the file */
415*7c478bd9Sstevel@tonic-gate 		if (!noerror) (void) freelkfile();
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate 	    } else noerror = FALSE;  /* Lock failed */
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 	    /* If something happened, close the lock file */
420*7c478bd9Sstevel@tonic-gate 	    if (!noerror)
421*7c478bd9Sstevel@tonic-gate 		(void) _closelkfile();
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 	} else noerror = FALSE;				/* Open failed */
424*7c478bd9Sstevel@tonic-gate 
425*7c478bd9Sstevel@tonic-gate 	/* Done */
426*7c478bd9Sstevel@tonic-gate 	return (noerror);
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate /*
430*7c478bd9Sstevel@tonic-gate  *  int writelks(tblcnt)
431*7c478bd9Sstevel@tonic-gate  *	int	tblcnt
432*7c478bd9Sstevel@tonic-gate  *
433*7c478bd9Sstevel@tonic-gate  *	writelks() writes the lock information to the lock file.  Lock
434*7c478bd9Sstevel@tonic-gate  *	information includes the number of locks (to be) in the table.
435*7c478bd9Sstevel@tonic-gate  *	Note that functions may still be appending new locks after this
436*7c478bd9Sstevel@tonic-gate  *	call...
437*7c478bd9Sstevel@tonic-gate  *
438*7c478bd9Sstevel@tonic-gate  *  Arguments:
439*7c478bd9Sstevel@tonic-gate  *	tblcnt	Number of locks in the lock table
440*7c478bd9Sstevel@tonic-gate  *
441*7c478bd9Sstevel@tonic-gate  *  Returns:
442*7c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise with "errno" containing an
443*7c478bd9Sstevel@tonic-gate  *	indication of the error.
444*7c478bd9Sstevel@tonic-gate  *
445*7c478bd9Sstevel@tonic-gate  *  Statics Used:
446*7c478bd9Sstevel@tonic-gate  *	lockcount	Number of locks to exist
447*7c478bd9Sstevel@tonic-gate  *	locklist	Table of locks (may not include new ones)
448*7c478bd9Sstevel@tonic-gate  *	lkfilefd	File descriptor of the lock file
449*7c478bd9Sstevel@tonic-gate  *
450*7c478bd9Sstevel@tonic-gate  *  Notes:
451*7c478bd9Sstevel@tonic-gate  *    - The number of locks that are going to be in the lock file
452*7c478bd9Sstevel@tonic-gate  *	is in the static variable "lockcount".  <tblcnt> indicates
453*7c478bd9Sstevel@tonic-gate  *	the number of entries in the lock table.
454*7c478bd9Sstevel@tonic-gate  */
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate static	int
writelks(int tblcnt)457*7c478bd9Sstevel@tonic-gate writelks(int tblcnt)
458*7c478bd9Sstevel@tonic-gate {
459*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
460*7c478bd9Sstevel@tonic-gate 	int		noerr;		/* FLAG, TRUE if all's well */
461*7c478bd9Sstevel@tonic-gate 	size_t		tblsz;		/* Size of the table to write */
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 	/* Initializations */
464*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 	/* Rewind the OA&M Device Lock File */
467*7c478bd9Sstevel@tonic-gate 	if (lseek(lkfilefd, 0L, 0) >= 0L)
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 	    /* Write the number of locks that will (eventually) exist */
470*7c478bd9Sstevel@tonic-gate 	    if (write(lkfilefd, &lockcount, sizeof (int)) == sizeof (int)) {
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate 		/* Write the table as we currently know it */
473*7c478bd9Sstevel@tonic-gate 		tblsz = tblcnt * sizeof (struct devlks);
474*7c478bd9Sstevel@tonic-gate 		if (tblsz)
475*7c478bd9Sstevel@tonic-gate 		    if (!write(lkfilefd, locklist, tblsz) == (ssize_t)tblsz)
476*7c478bd9Sstevel@tonic-gate 			noerr = FALSE;  /* Write of locks failed */
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;  /* write() of count failed */
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	else noerr = FALSE;  /* Rewind failed */
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate 	/* Return an indicator of our success */
483*7c478bd9Sstevel@tonic-gate 	return (noerr);
484*7c478bd9Sstevel@tonic-gate }
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate /*
487*7c478bd9Sstevel@tonic-gate  * int appendlk(key, alias)
488*7c478bd9Sstevel@tonic-gate  *	int	key
489*7c478bd9Sstevel@tonic-gate  *	char   *alias
490*7c478bd9Sstevel@tonic-gate  *
491*7c478bd9Sstevel@tonic-gate  *	Write device locking information to the device locking file.
492*7c478bd9Sstevel@tonic-gate  *
493*7c478bd9Sstevel@tonic-gate  *  Arguments:
494*7c478bd9Sstevel@tonic-gate  *	key	Key the device is being locked on
495*7c478bd9Sstevel@tonic-gate  *	alias	The device alias being locked
496*7c478bd9Sstevel@tonic-gate  *
497*7c478bd9Sstevel@tonic-gate  *  Returns:  int
498*7c478bd9Sstevel@tonic-gate  *	TRUE if we successfully appended a lock to the lock file,
499*7c478bd9Sstevel@tonic-gate  *	FALSE with "errno" set otherwise.
500*7c478bd9Sstevel@tonic-gate  *
501*7c478bd9Sstevel@tonic-gate  *  Static data used:
502*7c478bd9Sstevel@tonic-gate  *	lkfilefd	The open file descriptor for the open device
503*7c478bd9Sstevel@tonic-gate  *			locking file
504*7c478bd9Sstevel@tonic-gate  */
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate static	int
appendlk(int key,char * alias)507*7c478bd9Sstevel@tonic-gate appendlk(
508*7c478bd9Sstevel@tonic-gate 	int key,		/* Lock key */
509*7c478bd9Sstevel@tonic-gate 	char *alias)		/* Alias to lock */
510*7c478bd9Sstevel@tonic-gate {
511*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
512*7c478bd9Sstevel@tonic-gate 	struct devlks	lk;	/* Structure for writing a lock */
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	/* Set up the data to write */
515*7c478bd9Sstevel@tonic-gate 	lk.lk_key = key;
516*7c478bd9Sstevel@tonic-gate 	(void) strcpy(lk.lk_alias, alias);
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 	/* Write the data, returning an indicator of our success */
519*7c478bd9Sstevel@tonic-gate 	return (write(lkfilefd, &lk,
520*7c478bd9Sstevel@tonic-gate 	    sizeof (struct devlks)) == sizeof (struct devlks));
521*7c478bd9Sstevel@tonic-gate }
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate /*
524*7c478bd9Sstevel@tonic-gate  *  int compresslks()
525*7c478bd9Sstevel@tonic-gate  *
526*7c478bd9Sstevel@tonic-gate  *	This function compresses the lock table, squeezing out the empty
527*7c478bd9Sstevel@tonic-gate  *	lock entries.
528*7c478bd9Sstevel@tonic-gate  *
529*7c478bd9Sstevel@tonic-gate  *  Arguments:  none
530*7c478bd9Sstevel@tonic-gate  *
531*7c478bd9Sstevel@tonic-gate  *  Returns:  int
532*7c478bd9Sstevel@tonic-gate  *	The number of non-empty entries in the table.  They will be the
533*7c478bd9Sstevel@tonic-gate  *	first 'n' entries in the table after compression.
534*7c478bd9Sstevel@tonic-gate  *
535*7c478bd9Sstevel@tonic-gate  *  Statics Used
536*7c478bd9Sstevel@tonic-gate  *	lockcount	Number of locks in the device lock list
537*7c478bd9Sstevel@tonic-gate  *	locklist	The device lock list
538*7c478bd9Sstevel@tonic-gate  */
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate static	int
compresslks(void)541*7c478bd9Sstevel@tonic-gate compresslks(void)
542*7c478bd9Sstevel@tonic-gate {
543*7c478bd9Sstevel@tonic-gate 	/* Automatics */
544*7c478bd9Sstevel@tonic-gate 	struct devlks  *avail;		/* Pointer to empty slot */
545*7c478bd9Sstevel@tonic-gate 	struct devlks  *p;		/* Running pointer to locks */
546*7c478bd9Sstevel@tonic-gate 	int		nlocks;		/* Number of locks (up to date) */
547*7c478bd9Sstevel@tonic-gate 	int		i;		/* Temporary counter */
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	/* Initializations */
550*7c478bd9Sstevel@tonic-gate 	p = locklist;
551*7c478bd9Sstevel@tonic-gate 	nlocks = lockcount;
552*7c478bd9Sstevel@tonic-gate 	avail = NULL;
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate 	/* Loop through the lock list squeezing out unused slots */
555*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < lockcount; i++) {
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 	    /* If we've found an empty slot ... */
558*7c478bd9Sstevel@tonic-gate 	    if (isanullstr(p->lk_alias)) {
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 		/*
561*7c478bd9Sstevel@tonic-gate 		 * If we've an empty slot to move to, just decrement
562*7c478bd9Sstevel@tonic-gate 		 * count of used slots.  Otherwise, make it the next
563*7c478bd9Sstevel@tonic-gate 		 * available slot
564*7c478bd9Sstevel@tonic-gate 		 */
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 		nlocks--;
567*7c478bd9Sstevel@tonic-gate 		if (!avail) avail = p;
568*7c478bd9Sstevel@tonic-gate 	    }
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 	    else if (avail) {
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 		/*
573*7c478bd9Sstevel@tonic-gate 		 * If we found a slot in use and there's an
574*7c478bd9Sstevel@tonic-gate 		 * available slot, move this one there
575*7c478bd9Sstevel@tonic-gate 		 */
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 		(void) strcpy(avail->lk_alias, p->lk_alias);
578*7c478bd9Sstevel@tonic-gate 		avail->lk_key = p->lk_key;
579*7c478bd9Sstevel@tonic-gate 		avail++;
580*7c478bd9Sstevel@tonic-gate 	    }
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 	    /* Next, please */
583*7c478bd9Sstevel@tonic-gate 	    p++;
584*7c478bd9Sstevel@tonic-gate 	}
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate 	return (nlocks);
587*7c478bd9Sstevel@tonic-gate }
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate /*
590*7c478bd9Sstevel@tonic-gate  *  int freelkfile()
591*7c478bd9Sstevel@tonic-gate  *
592*7c478bd9Sstevel@tonic-gate  *	This function unlocks the OA&M device locking file.
593*7c478bd9Sstevel@tonic-gate  *
594*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
595*7c478bd9Sstevel@tonic-gate  *
596*7c478bd9Sstevel@tonic-gate  *  Returns:  int
597*7c478bd9Sstevel@tonic-gate  *	TRUE if it successfully unlocked the file, FALSE otherwise
598*7c478bd9Sstevel@tonic-gate  *	with "errno" set to indicate the problem.
599*7c478bd9Sstevel@tonic-gate  *
600*7c478bd9Sstevel@tonic-gate  *  Statics Used:
601*7c478bd9Sstevel@tonic-gate  *	lkinfo		File-locking structure
602*7c478bd9Sstevel@tonic-gate  *	lkfilefd	File-descriptor of the open lock file
603*7c478bd9Sstevel@tonic-gate  */
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate static	int
freelkfile(void)606*7c478bd9Sstevel@tonic-gate freelkfile(void)
607*7c478bd9Sstevel@tonic-gate {
608*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
609*7c478bd9Sstevel@tonic-gate 	int		noerr;		/* TRUE if all's well */
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate 	/* Set the action to "unlock" */
612*7c478bd9Sstevel@tonic-gate 	lkinfo.l_type = F_UNLCK;
613*7c478bd9Sstevel@tonic-gate 
614*7c478bd9Sstevel@tonic-gate 	/* Unlock the file */
615*7c478bd9Sstevel@tonic-gate 	noerr = (fcntl(lkfilefd, F_SETLK, &lkinfo) != -1);
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 	/* Return an indication of our success */
618*7c478bd9Sstevel@tonic-gate 	return (noerr);
619*7c478bd9Sstevel@tonic-gate }
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate /*
622*7c478bd9Sstevel@tonic-gate  * int putlocks(newlist, key)
623*7c478bd9Sstevel@tonic-gate  *	char  **newlist
624*7c478bd9Sstevel@tonic-gate  *	int	key
625*7c478bd9Sstevel@tonic-gate  *
626*7c478bd9Sstevel@tonic-gate  *	This function updates the file containing OA&M device locks.
627*7c478bd9Sstevel@tonic-gate  *
628*7c478bd9Sstevel@tonic-gate  *  Arguments:
629*7c478bd9Sstevel@tonic-gate  *	newlist		The address of the list of addresses of device
630*7c478bd9Sstevel@tonic-gate  *			aliases to add to the list of locked devices
631*7c478bd9Sstevel@tonic-gate  *	key		The key on which to lock the devices
632*7c478bd9Sstevel@tonic-gate  *
633*7c478bd9Sstevel@tonic-gate  *  Returns:  int
634*7c478bd9Sstevel@tonic-gate  *	TRUE if all went well, FALSE otherwise with "errno" set to an
635*7c478bd9Sstevel@tonic-gate  *	error code that indicates the problem.
636*7c478bd9Sstevel@tonic-gate  *
637*7c478bd9Sstevel@tonic-gate  *  Statics Used:
638*7c478bd9Sstevel@tonic-gate  *	lockcount	Number of locks in the locked device structure
639*7c478bd9Sstevel@tonic-gate  *	locklist	Locked device structure
640*7c478bd9Sstevel@tonic-gate  */
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate static	int
putlocks(char ** newlist,int key)643*7c478bd9Sstevel@tonic-gate putlocks(
644*7c478bd9Sstevel@tonic-gate 	char **newlist,	/* New devices to lock */
645*7c478bd9Sstevel@tonic-gate 	int key)	/* Key we're locking stuff on */
646*7c478bd9Sstevel@tonic-gate {
647*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
648*7c478bd9Sstevel@tonic-gate 	struct devlks  *plk;		/* Ptr into the locks list */
649*7c478bd9Sstevel@tonic-gate 	char		**pp;		/* Pointer into the device list */
650*7c478bd9Sstevel@tonic-gate 	char		**qq;		/* Another ptr into the dev list */
651*7c478bd9Sstevel@tonic-gate 	int		lkndx;		/* Index into locks list */
652*7c478bd9Sstevel@tonic-gate 	int		noerr;		/* TRUE if all's well */
653*7c478bd9Sstevel@tonic-gate 	int		lksintbl;	/* Number of locks in the table */
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 	/*
657*7c478bd9Sstevel@tonic-gate 	 * Look through the existing lock list, looking for holes we can
658*7c478bd9Sstevel@tonic-gate 	 * use for the newly locked devices
659*7c478bd9Sstevel@tonic-gate 	 */
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	plk = locklist;
662*7c478bd9Sstevel@tonic-gate 	pp = newlist;
663*7c478bd9Sstevel@tonic-gate 	lkndx = 0;
664*7c478bd9Sstevel@tonic-gate 	while (*pp && (lkndx < lockcount)) {
665*7c478bd9Sstevel@tonic-gate 	    if (isanullstr(plk->lk_alias)) {
666*7c478bd9Sstevel@tonic-gate 		plk->lk_key = key;
667*7c478bd9Sstevel@tonic-gate 		(void) strcpy(plk->lk_alias, *pp++);
668*7c478bd9Sstevel@tonic-gate 	    }
669*7c478bd9Sstevel@tonic-gate 	    lkndx++;
670*7c478bd9Sstevel@tonic-gate 	    plk++;
671*7c478bd9Sstevel@tonic-gate 	}
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 	/*
674*7c478bd9Sstevel@tonic-gate 	 * Update the locks file (algorithm depends on whether we're adding
675*7c478bd9Sstevel@tonic-gate 	 * new locks or not.  May be replacing old locks!)
676*7c478bd9Sstevel@tonic-gate 	 */
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate 	if (*pp) {
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate 	/*
681*7c478bd9Sstevel@tonic-gate 	 * Need to expand the locks file
682*7c478bd9Sstevel@tonic-gate 	 *  - Remember the old lock count (in existing lock buffer)
683*7c478bd9Sstevel@tonic-gate 	 *  - Count the number of new locks we need to add
684*7c478bd9Sstevel@tonic-gate 	 *  - Write out the old locks structure
685*7c478bd9Sstevel@tonic-gate 	 *  - Append locks for the newly added locks
686*7c478bd9Sstevel@tonic-gate 	 */
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate 	    lksintbl = lockcount;
689*7c478bd9Sstevel@tonic-gate 	    for (qq = pp; *qq; qq++) lockcount++;
690*7c478bd9Sstevel@tonic-gate 	    noerr = writelks(lksintbl);
691*7c478bd9Sstevel@tonic-gate 	    while (noerr && *pp) noerr = appendlk(key, *pp++);
692*7c478bd9Sstevel@tonic-gate 	} else {
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	/*
695*7c478bd9Sstevel@tonic-gate 	 * Don't need to expand the locks file.  Compress the locks
696*7c478bd9Sstevel@tonic-gate 	 * then write out the locks information
697*7c478bd9Sstevel@tonic-gate 	 */
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate 	    lockcount = compresslks();
700*7c478bd9Sstevel@tonic-gate 	    noerr = writelks(lockcount);
701*7c478bd9Sstevel@tonic-gate 	}
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate 	/* Done.  Return an indication of our success */
704*7c478bd9Sstevel@tonic-gate 	return (noerr);
705*7c478bd9Sstevel@tonic-gate }
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate /*
708*7c478bd9Sstevel@tonic-gate  * char *islocked(device)
709*7c478bd9Sstevel@tonic-gate  *	char	       *device
710*7c478bd9Sstevel@tonic-gate  *
711*7c478bd9Sstevel@tonic-gate  *	This function checks a device to see if it is locked.  If it is
712*7c478bd9Sstevel@tonic-gate  *	not locked, it returns the device alias.
713*7c478bd9Sstevel@tonic-gate  *
714*7c478bd9Sstevel@tonic-gate  *	A device is not locked if the device's alias does not appear in
715*7c478bd9Sstevel@tonic-gate  *	the device locks table, or the key on which the device was locked
716*7c478bd9Sstevel@tonic-gate  *	is no longer active.
717*7c478bd9Sstevel@tonic-gate  *
718*7c478bd9Sstevel@tonic-gate  *  Argumetns:
719*7c478bd9Sstevel@tonic-gate  *	char *device		The device to be reserved.  This can be
720*7c478bd9Sstevel@tonic-gate  *				a pathname to the device or a device
721*7c478bd9Sstevel@tonic-gate  *				alias.
722*7c478bd9Sstevel@tonic-gate  *
723*7c478bd9Sstevel@tonic-gate  *  Returns:  char *
724*7c478bd9Sstevel@tonic-gate  *	Returns a pointer to the device alias if it's not locked, or
725*7c478bd9Sstevel@tonic-gate  *	(char *) NULL if it's locked or some error occurred.
726*7c478bd9Sstevel@tonic-gate  *
727*7c478bd9Sstevel@tonic-gate  *  Static data used:
728*7c478bd9Sstevel@tonic-gate  *	struct devlks *locklist		Pointer to the list of device locks
729*7c478bd9Sstevel@tonic-gate  *	int lockcount			The number of devices that are locked
730*7c478bd9Sstevel@tonic-gate  */
731*7c478bd9Sstevel@tonic-gate 
732*7c478bd9Sstevel@tonic-gate static	char *
islocked(char * device)733*7c478bd9Sstevel@tonic-gate islocked(char *device)
734*7c478bd9Sstevel@tonic-gate {
735*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
736*7c478bd9Sstevel@tonic-gate 	char		*alias;		/* Alias of "device" */
737*7c478bd9Sstevel@tonic-gate 	struct devlks	*plk;		/* Ptr to locking info */
738*7c478bd9Sstevel@tonic-gate 	int		locked;		/* TRUE if device in locked list */
739*7c478bd9Sstevel@tonic-gate 	int		i;		/* Temp counter */
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate 	/* Get the device's alias */
742*7c478bd9Sstevel@tonic-gate 	if (alias = devattr(device, DTAB_ALIAS)) {
743*7c478bd9Sstevel@tonic-gate 
744*7c478bd9Sstevel@tonic-gate 	/*
745*7c478bd9Sstevel@tonic-gate 	 * Look through the device locks to see if this device alias
746*7c478bd9Sstevel@tonic-gate 	 * is locked
747*7c478bd9Sstevel@tonic-gate 	 */
748*7c478bd9Sstevel@tonic-gate 
749*7c478bd9Sstevel@tonic-gate 	    locked = FALSE;
750*7c478bd9Sstevel@tonic-gate 	    plk = locklist;
751*7c478bd9Sstevel@tonic-gate 	    for (i = 0; !locked && (i < lockcount); i++) {
752*7c478bd9Sstevel@tonic-gate 		if (strncmp(alias, plk->lk_alias, DTAB_MXALIASLN) == 0)
753*7c478bd9Sstevel@tonic-gate 		    locked = TRUE;
754*7c478bd9Sstevel@tonic-gate 		else plk++;
755*7c478bd9Sstevel@tonic-gate 	    }
756*7c478bd9Sstevel@tonic-gate 
757*7c478bd9Sstevel@tonic-gate 	    if (locked) {
758*7c478bd9Sstevel@tonic-gate 		    free(alias);
759*7c478bd9Sstevel@tonic-gate 		    alias = NULL;
760*7c478bd9Sstevel@tonic-gate 		    errno = EAGAIN;
761*7c478bd9Sstevel@tonic-gate 	    }
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate 	}  /* devattr() failed, no such device? */
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate 	/* Return pointer to the device */
766*7c478bd9Sstevel@tonic-gate 	return (alias);
767*7c478bd9Sstevel@tonic-gate }
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate /*
770*7c478bd9Sstevel@tonic-gate  *  int unreserv(key, device)
771*7c478bd9Sstevel@tonic-gate  *	int	key
772*7c478bd9Sstevel@tonic-gate  *	char   *device
773*7c478bd9Sstevel@tonic-gate  *
774*7c478bd9Sstevel@tonic-gate  *	This function removes a device reservation.
775*7c478bd9Sstevel@tonic-gate  *
776*7c478bd9Sstevel@tonic-gate  *  Arguments:
777*7c478bd9Sstevel@tonic-gate  *	int key	The key on which the device was allocated
778*7c478bd9Sstevel@tonic-gate  *	char *device	The device to be freed.
779*7c478bd9Sstevel@tonic-gate  *
780*7c478bd9Sstevel@tonic-gate  *  Returns:  int
781*7c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise with "errno" set.
782*7c478bd9Sstevel@tonic-gate  *
783*7c478bd9Sstevel@tonic-gate  *  Explicit "errno" settings:
784*7c478bd9Sstevel@tonic-gate  *	(This follows the "signal()" model which gives one the ability
785*7c478bd9Sstevel@tonic-gate  *	to determine if a device is allocated without having the
786*7c478bd9Sstevel@tonic-gate  *	permission to free it.)
787*7c478bd9Sstevel@tonic-gate  *
788*7c478bd9Sstevel@tonic-gate  *	EINVAL	The device specified was not locked
789*7c478bd9Sstevel@tonic-gate  *	EPERM	The device specified was locked but not on the
790*7c478bd9Sstevel@tonic-gate  *		specified key
791*7c478bd9Sstevel@tonic-gate  *
792*7c478bd9Sstevel@tonic-gate  *  Static data used:
793*7c478bd9Sstevel@tonic-gate  *	locklist	List of locked devices
794*7c478bd9Sstevel@tonic-gate  *	lockcount	Number of entries in the locked-device list
795*7c478bd9Sstevel@tonic-gate  */
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate int
unreserv(int key,char * device)798*7c478bd9Sstevel@tonic-gate unreserv(int key, char *device)
799*7c478bd9Sstevel@tonic-gate {
800*7c478bd9Sstevel@tonic-gate 	/* Automatics */
801*7c478bd9Sstevel@tonic-gate 	char		*srchalias;	/* Device alias to search table with */
802*7c478bd9Sstevel@tonic-gate 	char		*alias;		/* Device's alias (from devattr()) */
803*7c478bd9Sstevel@tonic-gate 	struct devlks	*plk;		/* Pointer to a device lock */
804*7c478bd9Sstevel@tonic-gate 	int		locked;		/* TRUE if device currently locked */
805*7c478bd9Sstevel@tonic-gate 	int		noerr;		/* TRUE if all's well */
806*7c478bd9Sstevel@tonic-gate 	int		olderrno;	/* Entry value of "errno" */
807*7c478bd9Sstevel@tonic-gate 	int		i;		/* Counter of locks */
808*7c478bd9Sstevel@tonic-gate 
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate 	/* Initializations */
811*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
812*7c478bd9Sstevel@tonic-gate 
813*7c478bd9Sstevel@tonic-gate 	/*
814*7c478bd9Sstevel@tonic-gate 	 * Get the device alias.  If none can be found, try to free
815*7c478bd9Sstevel@tonic-gate 	 * whatever it is that was given to us (the possibility exists
816*7c478bd9Sstevel@tonic-gate 	 * that the device has been removed from the device table since
817*7c478bd9Sstevel@tonic-gate 	 * it was reserved, so the device not being in the table shouldn't
818*7c478bd9Sstevel@tonic-gate 	 * pose too much of a problem with us...)
819*7c478bd9Sstevel@tonic-gate 	 */
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate 	olderrno = errno;
822*7c478bd9Sstevel@tonic-gate 	if (alias = devattr(device, DTAB_ALIAS)) srchalias = alias;
823*7c478bd9Sstevel@tonic-gate 	else {
824*7c478bd9Sstevel@tonic-gate 	    errno = olderrno;
825*7c478bd9Sstevel@tonic-gate 	    srchalias = device;
826*7c478bd9Sstevel@tonic-gate 	}
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate 	/* Loop through the locked-device list looking for what we've got... */
829*7c478bd9Sstevel@tonic-gate 	locked = FALSE;
830*7c478bd9Sstevel@tonic-gate 	plk = locklist;
831*7c478bd9Sstevel@tonic-gate 	for (i = 0; !locked && (i < lockcount); i++) {
832*7c478bd9Sstevel@tonic-gate 	    if (strcmp(srchalias, plk->lk_alias) == 0)
833*7c478bd9Sstevel@tonic-gate 		locked = TRUE;
834*7c478bd9Sstevel@tonic-gate 	    else plk++;
835*7c478bd9Sstevel@tonic-gate 	}
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate 	/* Free the alias string (if any), we don't need it anymore */
838*7c478bd9Sstevel@tonic-gate 	if (alias) free(alias);
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 	/* If the device is locked ... */
841*7c478bd9Sstevel@tonic-gate 	if (locked) {
842*7c478bd9Sstevel@tonic-gate 
843*7c478bd9Sstevel@tonic-gate 	/*
844*7c478bd9Sstevel@tonic-gate 	 * If it's locked on the key we've been given, free it.
845*7c478bd9Sstevel@tonic-gate 	 * Otherwise, don't free it and set errno to EPERM
846*7c478bd9Sstevel@tonic-gate 	 */
847*7c478bd9Sstevel@tonic-gate 
848*7c478bd9Sstevel@tonic-gate 	    if (plk->lk_key == key) {
849*7c478bd9Sstevel@tonic-gate 		plk->lk_alias[0] = '\0';
850*7c478bd9Sstevel@tonic-gate 	    } else {
851*7c478bd9Sstevel@tonic-gate 		noerr = FALSE;
852*7c478bd9Sstevel@tonic-gate 		errno = EPERM;
853*7c478bd9Sstevel@tonic-gate 	    }
854*7c478bd9Sstevel@tonic-gate 	} else {
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate 	    /* The device isn't locked.  Set errno to EINVAL */
857*7c478bd9Sstevel@tonic-gate 	    noerr = FALSE;
858*7c478bd9Sstevel@tonic-gate 	    errno = EINVAL;
859*7c478bd9Sstevel@tonic-gate 	}
860*7c478bd9Sstevel@tonic-gate 
861*7c478bd9Sstevel@tonic-gate 	/* Finished.  Return an indication of our success */
862*7c478bd9Sstevel@tonic-gate 	return (noerr);
863*7c478bd9Sstevel@tonic-gate }
864*7c478bd9Sstevel@tonic-gate 
865*7c478bd9Sstevel@tonic-gate /*
866*7c478bd9Sstevel@tonic-gate  *  char **devreserv(key, rsvlst)
867*7c478bd9Sstevel@tonic-gate  *	int		key
868*7c478bd9Sstevel@tonic-gate  *	char	      **rsvlist[]
869*7c478bd9Sstevel@tonic-gate  *
870*7c478bd9Sstevel@tonic-gate  *	The devreserv() function reserves devices known to the OA&M Device
871*7c478bd9Sstevel@tonic-gate  *	Management family of functions.  Once a device is reserved, it can't
872*7c478bd9Sstevel@tonic-gate  *	be reserved by another until it is freed or the process with the
873*7c478bd9Sstevel@tonic-gate  *	"key" is no longer active.  It returns a list aliases of the devices
874*7c478bd9Sstevel@tonic-gate  *	it allocated.
875*7c478bd9Sstevel@tonic-gate  *
876*7c478bd9Sstevel@tonic-gate  *	The function attempts to reserve a single device from each of the
877*7c478bd9Sstevel@tonic-gate  *	lists.  It scans each list sequentially until it was able to
878*7c478bd9Sstevel@tonic-gate  *	reserve a requested device.  If it successfully reserved a device
879*7c478bd9Sstevel@tonic-gate  *	from each of the lists, it updates the device-locked file and
880*7c478bd9Sstevel@tonic-gate  *	returns those aliases to the caller.  If it fails, it allocates
881*7c478bd9Sstevel@tonic-gate  *	nothing and returns (char **) NULL to the caller.  "errno"
882*7c478bd9Sstevel@tonic-gate  *	indicates the error.
883*7c478bd9Sstevel@tonic-gate  *
884*7c478bd9Sstevel@tonic-gate  *  Arguments:
885*7c478bd9Sstevel@tonic-gate  *	int key			The key on which this device is being reserved.
886*7c478bd9Sstevel@tonic-gate  *
887*7c478bd9Sstevel@tonic-gate  *	char **rsvlist[]	The address of the list of addresses of lists
888*7c478bd9Sstevel@tonic-gate  *				of pointers to the devices to allocate.
889*7c478bd9Sstevel@tonic-gate  *
890*7c478bd9Sstevel@tonic-gate  *  Returns:  char **
891*7c478bd9Sstevel@tonic-gate  *	A pointer to malloc()ed space containing pointers to the aliases
892*7c478bd9Sstevel@tonic-gate  *	of the reserved devices.  The aliases are in malloc()ed space also.
893*7c478bd9Sstevel@tonic-gate  *	The list is terminated by the value (char *) NULL.
894*7c478bd9Sstevel@tonic-gate  *
895*7c478bd9Sstevel@tonic-gate  *  Static Data Used:
896*7c478bd9Sstevel@tonic-gate  *	None directly, but functions called share hidden information
897*7c478bd9Sstevel@tonic-gate  *	that really isn't of concern to devreserv().
898*7c478bd9Sstevel@tonic-gate  */
899*7c478bd9Sstevel@tonic-gate 
900*7c478bd9Sstevel@tonic-gate char **
devreserv(int key,char ** rsvlst[])901*7c478bd9Sstevel@tonic-gate devreserv(
902*7c478bd9Sstevel@tonic-gate 	int		key,		/* Key to reserve device on */
903*7c478bd9Sstevel@tonic-gate 	char		**rsvlst[])	/* List of lists of devs to reserve */
904*7c478bd9Sstevel@tonic-gate {
905*7c478bd9Sstevel@tonic-gate 	char		***ppp;		/* Ptr to current list in rsvlist */
906*7c478bd9Sstevel@tonic-gate 	char		**pp;		/* Ptr to current item in list */
907*7c478bd9Sstevel@tonic-gate 	char		**qq;		/* Ptr to item in rtnlist */
908*7c478bd9Sstevel@tonic-gate 	char		**rr;		/* Ptr to item in aliases */
909*7c478bd9Sstevel@tonic-gate 	char		**aliases;	/* List of aliases allocated */
910*7c478bd9Sstevel@tonic-gate 	char		**rtnlist;	/* Ptr to buf to return */
911*7c478bd9Sstevel@tonic-gate 	char		*alias;		/* Alias of dev to reserve */
912*7c478bd9Sstevel@tonic-gate 	int		noerr;		/* TRUE if all's well */
913*7c478bd9Sstevel@tonic-gate 	int		olderrno;	/* Old value of errno */
914*7c478bd9Sstevel@tonic-gate 	int		gotone;		/* TRUE if unreserved dev found */
915*7c478bd9Sstevel@tonic-gate 	int		foundone;	/* Found a valid device in the list */
916*7c478bd9Sstevel@tonic-gate 	int		ndevs;		/* # of devs to reserve */
917*7c478bd9Sstevel@tonic-gate 
918*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
919*7c478bd9Sstevel@tonic-gate 	ppp = rsvlst;
920*7c478bd9Sstevel@tonic-gate 	olderrno = errno;
921*7c478bd9Sstevel@tonic-gate 	for (ndevs = 0; *ppp++; ndevs++)
922*7c478bd9Sstevel@tonic-gate 		;
923*7c478bd9Sstevel@tonic-gate 	if (rtnlist = malloc((ndevs+1)*sizeof (char **))) {
924*7c478bd9Sstevel@tonic-gate 	    if (aliases = malloc((ndevs+1)*sizeof (char **))) {
925*7c478bd9Sstevel@tonic-gate 		if (getlocks()) {
926*7c478bd9Sstevel@tonic-gate 		    qq = rtnlist;
927*7c478bd9Sstevel@tonic-gate 		    rr = aliases;
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 		    /* Go through the lists of devices we're to reserve */
930*7c478bd9Sstevel@tonic-gate 
931*7c478bd9Sstevel@tonic-gate 		    for (ppp = rsvlst; noerr && *ppp; ppp++) {
932*7c478bd9Sstevel@tonic-gate 
933*7c478bd9Sstevel@tonic-gate 			/* Try to reserve a device from each list */
934*7c478bd9Sstevel@tonic-gate 			gotone = FALSE;
935*7c478bd9Sstevel@tonic-gate 			foundone = FALSE;
936*7c478bd9Sstevel@tonic-gate 			for (pp = *ppp; noerr && !gotone && *pp; pp++) {
937*7c478bd9Sstevel@tonic-gate 
938*7c478bd9Sstevel@tonic-gate 			/*
939*7c478bd9Sstevel@tonic-gate 			 * Check the next device in the list.  If islocked()
940*7c478bd9Sstevel@tonic-gate 			 * returns that device's alias, it's ours to have
941*7c478bd9Sstevel@tonic-gate 			 */
942*7c478bd9Sstevel@tonic-gate 
943*7c478bd9Sstevel@tonic-gate 			    if (alias = islocked(*pp)) {
944*7c478bd9Sstevel@tonic-gate 				gotone = TRUE;
945*7c478bd9Sstevel@tonic-gate 				foundone = TRUE;
946*7c478bd9Sstevel@tonic-gate 				if (*qq = malloc(strlen(*pp)+1)) {
947*7c478bd9Sstevel@tonic-gate 				    (void) strcpy(*qq++, *pp);
948*7c478bd9Sstevel@tonic-gate 				    *rr++ = alias;
949*7c478bd9Sstevel@tonic-gate 				} else {
950*7c478bd9Sstevel@tonic-gate 				    *rr = NULL;
951*7c478bd9Sstevel@tonic-gate 				    noerr = FALSE;
952*7c478bd9Sstevel@tonic-gate 				}
953*7c478bd9Sstevel@tonic-gate 			    } else {
954*7c478bd9Sstevel@tonic-gate 				if (errno == EAGAIN) {
955*7c478bd9Sstevel@tonic-gate 				    foundone = TRUE;
956*7c478bd9Sstevel@tonic-gate 				    errno = olderrno;
957*7c478bd9Sstevel@tonic-gate 				} else if (errno == ENODEV) errno = olderrno;
958*7c478bd9Sstevel@tonic-gate 				else {
959*7c478bd9Sstevel@tonic-gate 				    noerr = FALSE;
960*7c478bd9Sstevel@tonic-gate 				    *rr = NULL;
961*7c478bd9Sstevel@tonic-gate 				}
962*7c478bd9Sstevel@tonic-gate 			    }
963*7c478bd9Sstevel@tonic-gate 			}
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 			/*
966*7c478bd9Sstevel@tonic-gate 			 * If no device from the list could be reserved,
967*7c478bd9Sstevel@tonic-gate 			 * we've failed
968*7c478bd9Sstevel@tonic-gate 			 */
969*7c478bd9Sstevel@tonic-gate 
970*7c478bd9Sstevel@tonic-gate 			if (noerr && !gotone) {
971*7c478bd9Sstevel@tonic-gate 			    noerr = FALSE;
972*7c478bd9Sstevel@tonic-gate 			    if (!foundone) errno = ENODEV;
973*7c478bd9Sstevel@tonic-gate 			    else errno = EAGAIN;
974*7c478bd9Sstevel@tonic-gate 			    *qq = NULL;
975*7c478bd9Sstevel@tonic-gate 			    *rr = NULL;
976*7c478bd9Sstevel@tonic-gate 			}
977*7c478bd9Sstevel@tonic-gate 
978*7c478bd9Sstevel@tonic-gate 		    } /* End of loop through lists loop */
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 		/*
981*7c478bd9Sstevel@tonic-gate 		 * If all went well, update lock file.
982*7c478bd9Sstevel@tonic-gate 		 * Then, free locks
983*7c478bd9Sstevel@tonic-gate 		 */
984*7c478bd9Sstevel@tonic-gate 
985*7c478bd9Sstevel@tonic-gate 		    if (noerr) {
986*7c478bd9Sstevel@tonic-gate 			*qq = NULL;
987*7c478bd9Sstevel@tonic-gate 			*rr = NULL;
988*7c478bd9Sstevel@tonic-gate 			if (!putlocks(aliases, key)) noerr = FALSE;
989*7c478bd9Sstevel@tonic-gate 		    }
990*7c478bd9Sstevel@tonic-gate 
991*7c478bd9Sstevel@tonic-gate 		    /* Free resources */
992*7c478bd9Sstevel@tonic-gate 		    if (!freelkfile()) noerr = FALSE;
993*7c478bd9Sstevel@tonic-gate 		    if (_closelkfile() != 0) noerr = FALSE;
994*7c478bd9Sstevel@tonic-gate 		    for (qq = aliases; *qq; qq++) free(*qq);
995*7c478bd9Sstevel@tonic-gate 		    if (!noerr)
996*7c478bd9Sstevel@tonic-gate 			for (pp = rtnlist; *pp; pp++)
997*7c478bd9Sstevel@tonic-gate 				free(*pp);
998*7c478bd9Sstevel@tonic-gate 
999*7c478bd9Sstevel@tonic-gate 		} else noerr = FALSE; /* Error getting locks */
1000*7c478bd9Sstevel@tonic-gate 
1001*7c478bd9Sstevel@tonic-gate 		free(aliases);
1002*7c478bd9Sstevel@tonic-gate 
1003*7c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;  /* Malloc() for alias list failed */
1004*7c478bd9Sstevel@tonic-gate 
1005*7c478bd9Sstevel@tonic-gate 	    if (!noerr) {
1006*7c478bd9Sstevel@tonic-gate 		free(rtnlist);
1007*7c478bd9Sstevel@tonic-gate 		rtnlist = NULL;
1008*7c478bd9Sstevel@tonic-gate 	    }
1009*7c478bd9Sstevel@tonic-gate 
1010*7c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;  /* malloc() failed */
1011*7c478bd9Sstevel@tonic-gate 
1012*7c478bd9Sstevel@tonic-gate 	/* Return list or an indication of an error */
1013*7c478bd9Sstevel@tonic-gate 	return (noerr ? rtnlist : NULL);
1014*7c478bd9Sstevel@tonic-gate }
1015*7c478bd9Sstevel@tonic-gate 
1016*7c478bd9Sstevel@tonic-gate /*
1017*7c478bd9Sstevel@tonic-gate  *  int devfree(key, device)
1018*7c478bd9Sstevel@tonic-gate  *	int	key
1019*7c478bd9Sstevel@tonic-gate  *	char   *device
1020*7c478bd9Sstevel@tonic-gate  *
1021*7c478bd9Sstevel@tonic-gate  *	This function unreserves (frees) the given device.  It returns
1022*7c478bd9Sstevel@tonic-gate  *	an indication of success with "errno" containing information about
1023*7c478bd9Sstevel@tonic-gate  *	a failure.
1024*7c478bd9Sstevel@tonic-gate  *
1025*7c478bd9Sstevel@tonic-gate  *  Arguments:
1026*7c478bd9Sstevel@tonic-gate  *	int	key	The key that the device is locked on
1027*7c478bd9Sstevel@tonic-gate  *	char   *device	The device (alias, pathname to, etc.) to be freed.
1028*7c478bd9Sstevel@tonic-gate  *
1029*7c478bd9Sstevel@tonic-gate  *  Returns:  int
1030*7c478bd9Sstevel@tonic-gate  *	0 if successful, -1 with "errno" set if fails.
1031*7c478bd9Sstevel@tonic-gate  */
1032*7c478bd9Sstevel@tonic-gate 
1033*7c478bd9Sstevel@tonic-gate int
devfree(int key,char * device)1034*7c478bd9Sstevel@tonic-gate devfree(
1035*7c478bd9Sstevel@tonic-gate 	int	key,			/* Key device is locked on */
1036*7c478bd9Sstevel@tonic-gate 	char   *device)			/* Device to free */
1037*7c478bd9Sstevel@tonic-gate {
1038*7c478bd9Sstevel@tonic-gate 	/* Automatics */
1039*7c478bd9Sstevel@tonic-gate 	int	noerr;
1040*7c478bd9Sstevel@tonic-gate 
1041*7c478bd9Sstevel@tonic-gate 	/* Initializations */
1042*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
1043*7c478bd9Sstevel@tonic-gate 
1044*7c478bd9Sstevel@tonic-gate 	/* Get the locks, locking the lock file */
1045*7c478bd9Sstevel@tonic-gate 	if (getlocks()) {
1046*7c478bd9Sstevel@tonic-gate 
1047*7c478bd9Sstevel@tonic-gate 	    /* Attempt to unreserve the device */
1048*7c478bd9Sstevel@tonic-gate 	    if (unreserv(key, device)) {
1049*7c478bd9Sstevel@tonic-gate 
1050*7c478bd9Sstevel@tonic-gate 		/*
1051*7c478bd9Sstevel@tonic-gate 		 * Successful.  Compress the lock structure and
1052*7c478bd9Sstevel@tonic-gate 		 * write the new locks
1053*7c478bd9Sstevel@tonic-gate 		 */
1054*7c478bd9Sstevel@tonic-gate 
1055*7c478bd9Sstevel@tonic-gate 		lockcount = compresslks();
1056*7c478bd9Sstevel@tonic-gate 		if (!writelks(lockcount)) noerr = FALSE;
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;  /* Couldn't unreserve the device */
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 	    /* Unlock and close the locks file */
1061*7c478bd9Sstevel@tonic-gate 	    if (!freelkfile()) noerr = FALSE;
1062*7c478bd9Sstevel@tonic-gate 	    if (_closelkfile() != 0) noerr = FALSE;
1063*7c478bd9Sstevel@tonic-gate 
1064*7c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;
1065*7c478bd9Sstevel@tonic-gate 
1066*7c478bd9Sstevel@tonic-gate 	/* Return 0 if successful, something else otherwise */
1067*7c478bd9Sstevel@tonic-gate 	return (noerr? 0 : -1);
1068*7c478bd9Sstevel@tonic-gate }
1069*7c478bd9Sstevel@tonic-gate 
1070*7c478bd9Sstevel@tonic-gate /*
1071*7c478bd9Sstevel@tonic-gate  *  struct reservdev **reservdev()
1072*7c478bd9Sstevel@tonic-gate  *
1073*7c478bd9Sstevel@tonic-gate  *	This function returns the list of reserved devices
1074*7c478bd9Sstevel@tonic-gate  *	along with the key on which those devices were locked.
1075*7c478bd9Sstevel@tonic-gate  *
1076*7c478bd9Sstevel@tonic-gate  *  Arguments:  None.
1077*7c478bd9Sstevel@tonic-gate  *
1078*7c478bd9Sstevel@tonic-gate  *  Returns:  struct reservdev **
1079*7c478bd9Sstevel@tonic-gate  *	Pointer to the list of pointers to structures describing
1080*7c478bd9Sstevel@tonic-gate  *	the reserved devices, or (struct reservdev **) NULL if an
1081*7c478bd9Sstevel@tonic-gate  *	error occurred.  The list of pointers is terminated by
1082*7c478bd9Sstevel@tonic-gate  *	(struct reservdev *) NULL.
1083*7c478bd9Sstevel@tonic-gate  *
1084*7c478bd9Sstevel@tonic-gate  *  Statics Used:
1085*7c478bd9Sstevel@tonic-gate  *	locklist	List of reserved devices
1086*7c478bd9Sstevel@tonic-gate  *	lockcount	Number of items in the reserved-devices list
1087*7c478bd9Sstevel@tonic-gate  */
1088*7c478bd9Sstevel@tonic-gate 
1089*7c478bd9Sstevel@tonic-gate struct reservdev **
reservdev(void)1090*7c478bd9Sstevel@tonic-gate reservdev(void)
1091*7c478bd9Sstevel@tonic-gate {
1092*7c478bd9Sstevel@tonic-gate 	/* Automatics */
1093*7c478bd9Sstevel@tonic-gate 	struct reservdev	**rtnlist;	/* Ptr to return list */
1094*7c478bd9Sstevel@tonic-gate 	struct devlks		*p;		/* Running ptr, locklist */
1095*7c478bd9Sstevel@tonic-gate 	struct reservdev	**q;		/* Running ptr, rtnlist */
1096*7c478bd9Sstevel@tonic-gate 	char			*r;		/* Temp ptr to char */
1097*7c478bd9Sstevel@tonic-gate 	size_t			bufsiz;		/* Size of buffer to alloc */
1098*7c478bd9Sstevel@tonic-gate 	int			noerr;		/* TRUE if all's well */
1099*7c478bd9Sstevel@tonic-gate 	int			i;		/* Lock counter */
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate 
1102*7c478bd9Sstevel@tonic-gate 	/* Initializations */
1103*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
1104*7c478bd9Sstevel@tonic-gate 
1105*7c478bd9Sstevel@tonic-gate 	/* Open the lock file ... */
1106*7c478bd9Sstevel@tonic-gate 	if (_openlkfile()) {
1107*7c478bd9Sstevel@tonic-gate 
1108*7c478bd9Sstevel@tonic-gate 	    /* Put a read-lock on the lock-file ... */
1109*7c478bd9Sstevel@tonic-gate 	    if (locklkfile(F_RDLCK)) {
1110*7c478bd9Sstevel@tonic-gate 
1111*7c478bd9Sstevel@tonic-gate 		/* Read the locks ... */
1112*7c478bd9Sstevel@tonic-gate 		if (readlocks()) {
1113*7c478bd9Sstevel@tonic-gate 
1114*7c478bd9Sstevel@tonic-gate 		    /* Alloc space for the return list */
1115*7c478bd9Sstevel@tonic-gate 		    bufsiz = (lockcount+1) * sizeof (struct reservdev *);
1116*7c478bd9Sstevel@tonic-gate 		    if (rtnlist = malloc(bufsiz)) {
1117*7c478bd9Sstevel@tonic-gate 
1118*7c478bd9Sstevel@tonic-gate 			/* Build the return list from the lock list */
1119*7c478bd9Sstevel@tonic-gate 			p = locklist;
1120*7c478bd9Sstevel@tonic-gate 			q = rtnlist;
1121*7c478bd9Sstevel@tonic-gate 			for (i = 0; noerr && (i < lockcount); i++) {
1122*7c478bd9Sstevel@tonic-gate 			    if (*q = malloc(sizeof (struct reservdev))) {
1123*7c478bd9Sstevel@tonic-gate 				if (r = malloc(strlen(p->lk_alias)+1)) {
1124*7c478bd9Sstevel@tonic-gate 				    (*q)->devname = strcpy(r, p->lk_alias);
1125*7c478bd9Sstevel@tonic-gate 				    (*q)->key = p->lk_key;
1126*7c478bd9Sstevel@tonic-gate 				} else noerr = FALSE;  /* malloc() error */
1127*7c478bd9Sstevel@tonic-gate 			    } else noerr = FALSE;  /* malloc() error */
1128*7c478bd9Sstevel@tonic-gate 			    p++;
1129*7c478bd9Sstevel@tonic-gate 			    q++;
1130*7c478bd9Sstevel@tonic-gate 			}
1131*7c478bd9Sstevel@tonic-gate 
1132*7c478bd9Sstevel@tonic-gate 			/*
1133*7c478bd9Sstevel@tonic-gate 			 * If no error, terminate the list.  Otherwise, free
1134*7c478bd9Sstevel@tonic-gate 			 * the space we've allocated
1135*7c478bd9Sstevel@tonic-gate 			 */
1136*7c478bd9Sstevel@tonic-gate 
1137*7c478bd9Sstevel@tonic-gate 			if (noerr) *q = NULL;
1138*7c478bd9Sstevel@tonic-gate 			else {
1139*7c478bd9Sstevel@tonic-gate 			    for (q = rtnlist; *q; q++) {
1140*7c478bd9Sstevel@tonic-gate 				free((*q)->devname);
1141*7c478bd9Sstevel@tonic-gate 				free(*q);
1142*7c478bd9Sstevel@tonic-gate 			    }
1143*7c478bd9Sstevel@tonic-gate 			    free(rtnlist);
1144*7c478bd9Sstevel@tonic-gate 			}
1145*7c478bd9Sstevel@tonic-gate 
1146*7c478bd9Sstevel@tonic-gate 		    } else noerr = FALSE;  /* Couldn't malloc() list space */
1147*7c478bd9Sstevel@tonic-gate 
1148*7c478bd9Sstevel@tonic-gate 		} else noerr = FALSE;  /* Problem reading locks */
1149*7c478bd9Sstevel@tonic-gate 
1150*7c478bd9Sstevel@tonic-gate 		/* Free the lock file */
1151*7c478bd9Sstevel@tonic-gate 		(void) freelkfile();
1152*7c478bd9Sstevel@tonic-gate 
1153*7c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;  /* Error locking the lock file */
1154*7c478bd9Sstevel@tonic-gate 
1155*7c478bd9Sstevel@tonic-gate 	    /* Close the lock file */
1156*7c478bd9Sstevel@tonic-gate 	    (void) _closelkfile();
1157*7c478bd9Sstevel@tonic-gate 
1158*7c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;  /* Error opening the lock file */
1159*7c478bd9Sstevel@tonic-gate 
1160*7c478bd9Sstevel@tonic-gate 	/* Return ptr to list of locks or NULL if an error has occurred */
1161*7c478bd9Sstevel@tonic-gate 	return (noerr ? rtnlist : NULL);
1162*7c478bd9Sstevel@tonic-gate }
1163