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