xref: /titanic_51/usr/src/cmd/svr4pkg/pkgadm/lock.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland 
28*5c51f124SMoriah Waterland /*
29*5c51f124SMoriah Waterland  * Module: lock.c
30*5c51f124SMoriah Waterland  * Program: pkgadm (/usr/bin/pkgadm)
31*5c51f124SMoriah Waterland  * Synopsis: implements the zone/package administrative lock interface
32*5c51f124SMoriah Waterland  * Public methods:
33*5c51f124SMoriah Waterland  *	admin_lock
34*5c51f124SMoriah Waterland  * Usage:
35*5c51f124SMoriah Waterland  *  Acquire: -a [ -e | -s ] [ -o obj ] [ -k key ] [ -R root ] [ -q ] \
36*5c51f124SMoriah Waterland  *		[ -w ] [ -W timeout ]
37*5c51f124SMoriah Waterland  *  Release: -r -o object -k key [ -R altRoot ] [ -q ]
38*5c51f124SMoriah Waterland  *  Status: [ -o object ] [ -k key ] [ -R altRoot ] [ -q ]
39*5c51f124SMoriah Waterland  */
40*5c51f124SMoriah Waterland 
41*5c51f124SMoriah Waterland /* enable extentions to standard Unix libraries */
42*5c51f124SMoriah Waterland 
43*5c51f124SMoriah Waterland #define	__EXTENSIONS__
44*5c51f124SMoriah Waterland 
45*5c51f124SMoriah Waterland /* unix system includes */
46*5c51f124SMoriah Waterland 
47*5c51f124SMoriah Waterland #include <stdio.h>
48*5c51f124SMoriah Waterland #include <stdarg.h>
49*5c51f124SMoriah Waterland #include <stdlib.h>
50*5c51f124SMoriah Waterland #include <string.h>
51*5c51f124SMoriah Waterland #include <strings.h>
52*5c51f124SMoriah Waterland #include <sys/types.h>
53*5c51f124SMoriah Waterland #include <wait.h>
54*5c51f124SMoriah Waterland #include <sys/stat.h>
55*5c51f124SMoriah Waterland #include <fcntl.h>
56*5c51f124SMoriah Waterland #include <unistd.h>
57*5c51f124SMoriah Waterland #include <signal.h>
58*5c51f124SMoriah Waterland #include <locale.h>
59*5c51f124SMoriah Waterland #include <libgen.h>
60*5c51f124SMoriah Waterland #include <sys/param.h>
61*5c51f124SMoriah Waterland #include <openssl/bio.h>
62*5c51f124SMoriah Waterland #include <errno.h>
63*5c51f124SMoriah Waterland #include <assert.h>
64*5c51f124SMoriah Waterland #include <time.h>
65*5c51f124SMoriah Waterland #include <fnmatch.h>
66*5c51f124SMoriah Waterland #include <zone.h>
67*5c51f124SMoriah Waterland 
68*5c51f124SMoriah Waterland /* local includes */
69*5c51f124SMoriah Waterland 
70*5c51f124SMoriah Waterland #include <libinst.h>
71*5c51f124SMoriah Waterland #include <pkglib.h>
72*5c51f124SMoriah Waterland #include <pkgerr.h>
73*5c51f124SMoriah Waterland #include <keystore.h>
74*5c51f124SMoriah Waterland #include "pkgadm.h"
75*5c51f124SMoriah Waterland #include "pkgadm_msgs.h"
76*5c51f124SMoriah Waterland 
77*5c51f124SMoriah Waterland /* definition and conversion of sleep units */
78*5c51f124SMoriah Waterland 
79*5c51f124SMoriah Waterland #define	SECONDS(x)		((unsigned int)(x))
80*5c51f124SMoriah Waterland #define	MINUTES(x)		((unsigned int)(seconds(x)*60))
81*5c51f124SMoriah Waterland 
82*5c51f124SMoriah Waterland /* define how waits are timed */
83*5c51f124SMoriah Waterland 
84*5c51f124SMoriah Waterland #define	WAITER_INITIAL		SECONDS(1)
85*5c51f124SMoriah Waterland #define	WAITER_MAX		SECONDS(60)
86*5c51f124SMoriah Waterland #define	WAITER_NEXT(x)		((x)*2)
87*5c51f124SMoriah Waterland 
88*5c51f124SMoriah Waterland typedef unsigned int		WAITER_T;
89*5c51f124SMoriah Waterland 
90*5c51f124SMoriah Waterland /*
91*5c51f124SMoriah Waterland  * The administrative lock file resides in /tmp
92*5c51f124SMoriah Waterland  * It does not survive a reboot
93*5c51f124SMoriah Waterland  * It consists of fixed length records
94*5c51f124SMoriah Waterland  * Each record has the following information:
95*5c51f124SMoriah Waterland  * 	record number - record position within the lock file
96*5c51f124SMoriah Waterland  * 	lock count - number of lock holders maintaining this lock
97*5c51f124SMoriah Waterland  * 	lock object - object being locked
98*5c51f124SMoriah Waterland  * 	lock key - key needed to manipulate existing lock
99*5c51f124SMoriah Waterland  *	lock exclusive - is the lock exclusive (single locker only)
100*5c51f124SMoriah Waterland  */
101*5c51f124SMoriah Waterland 
102*5c51f124SMoriah Waterland #define	LOCK_OBJECT_MAXLEN	512-1
103*5c51f124SMoriah Waterland #define	LOCK_KEY_MAXLEN		37
104*5c51f124SMoriah Waterland 
105*5c51f124SMoriah Waterland #define	LOCK_DIRECTORY		"/tmp"
106*5c51f124SMoriah Waterland 
107*5c51f124SMoriah Waterland /*
108*5c51f124SMoriah Waterland  * this is the "well known name" of the lock file that is used by the
109*5c51f124SMoriah Waterland  * package, patch, and zone administration commands to synchronize their
110*5c51f124SMoriah Waterland  * various efforts - it must live in a temporary directory that is cleared
111*5c51f124SMoriah Waterland  * on system reboot but it is NOT a temporary file in that it survives
112*5c51f124SMoriah Waterland  * the process that creates and updates it - if the format of the lock
113*5c51f124SMoriah Waterland  * file ever changes, this path should be updated with a later "uuid"
114*5c51f124SMoriah Waterland  * so that previous (incompatible) pkgadm's will not use the later data.
115*5c51f124SMoriah Waterland  */
116*5c51f124SMoriah Waterland 
117*5c51f124SMoriah Waterland #define	LOCK_FILENAME	\
118*5c51f124SMoriah Waterland 	"/tmp/.ai.pkg.zone.lock-afdb66cf-1dd1-11b2-a049-000d560ddc3e"
119*5c51f124SMoriah Waterland 
120*5c51f124SMoriah Waterland /* mode to use for LOCK_FILENAME */
121*5c51f124SMoriah Waterland 
122*5c51f124SMoriah Waterland #define	LOCK_FILEMODE	\
123*5c51f124SMoriah Waterland 	(S_ISGID|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
124*5c51f124SMoriah Waterland 
125*5c51f124SMoriah Waterland #define	LOCK_SLEEP_INTERVAL	SECONDS(2)
126*5c51f124SMoriah Waterland 
127*5c51f124SMoriah Waterland /* lock contents types */
128*5c51f124SMoriah Waterland 
129*5c51f124SMoriah Waterland typedef unsigned long RECORDNUM_T;
130*5c51f124SMoriah Waterland 
131*5c51f124SMoriah Waterland #define	RECORDNUM_NONE	0xFFFFFFFF
132*5c51f124SMoriah Waterland 
133*5c51f124SMoriah Waterland /* actual lock data */
134*5c51f124SMoriah Waterland 
135*5c51f124SMoriah Waterland struct _adminLock
136*5c51f124SMoriah Waterland {
137*5c51f124SMoriah Waterland 	RECORDNUM_T	lockRecordNum;
138*5c51f124SMoriah Waterland 	unsigned long	lockCount;
139*5c51f124SMoriah Waterland 	unsigned long	lockExclusive;
140*5c51f124SMoriah Waterland 	pid_t		lockPid;
141*5c51f124SMoriah Waterland 	zoneid_t	lockZoneId;
142*5c51f124SMoriah Waterland 	char		lockKey[LOCK_KEY_MAXLEN+1];
143*5c51f124SMoriah Waterland 	char		lockObject[LOCK_OBJECT_MAXLEN+1];
144*5c51f124SMoriah Waterland };
145*5c51f124SMoriah Waterland 
146*5c51f124SMoriah Waterland typedef struct _adminLock ADMINLOCK_T;
147*5c51f124SMoriah Waterland 
148*5c51f124SMoriah Waterland /* size of an individual "lock" */
149*5c51f124SMoriah Waterland 
150*5c51f124SMoriah Waterland #define	LOCK_SIZE		sizeof (ADMINLOCK_T)
151*5c51f124SMoriah Waterland 
152*5c51f124SMoriah Waterland /* union to allow lock to be accessed as raw or structured data */
153*5c51f124SMoriah Waterland 
154*5c51f124SMoriah Waterland union _lockRecord
155*5c51f124SMoriah Waterland {
156*5c51f124SMoriah Waterland 	char		_lrLockData[LOCK_SIZE];
157*5c51f124SMoriah Waterland 	ADMINLOCK_T	_lrLock;
158*5c51f124SMoriah Waterland };
159*5c51f124SMoriah Waterland 
160*5c51f124SMoriah Waterland typedef union _lockRecord LOCK_T;
161*5c51f124SMoriah Waterland 
162*5c51f124SMoriah Waterland /* return codes from "_findLock" */
163*5c51f124SMoriah Waterland 
164*5c51f124SMoriah Waterland typedef unsigned long FINDLOCK_T;
165*5c51f124SMoriah Waterland 
166*5c51f124SMoriah Waterland #define	FINDLOCK_FOUND		((FINDLOCK_T)0)
167*5c51f124SMoriah Waterland #define	FINDLOCK_ERROR		((FINDLOCK_T)-1)
168*5c51f124SMoriah Waterland #define	FINDLOCK_NOTFOUND	((FINDLOCK_T)-2)
169*5c51f124SMoriah Waterland #define	FINDLOCK_KEYMISMATCH	((FINDLOCK_T)-3)
170*5c51f124SMoriah Waterland #define	FINDLOCK_LOCKED		((FINDLOCK_T)-4)
171*5c51f124SMoriah Waterland #define	FINDLOCK_NOTLOCKED	((FINDLOCK_T)-5)
172*5c51f124SMoriah Waterland #define	FINDLOCK_LOCKACQUIRED	((FINDLOCK_T)-6)
173*5c51f124SMoriah Waterland 
174*5c51f124SMoriah Waterland /*
175*5c51f124SMoriah Waterland  * Forward declarations
176*5c51f124SMoriah Waterland  */
177*5c51f124SMoriah Waterland 
178*5c51f124SMoriah Waterland /* local main function implementation methods */
179*5c51f124SMoriah Waterland 
180*5c51f124SMoriah Waterland static FINDLOCK_T	lock_acquire(LOCK_T *a_lock, int *a_fd, char *a_root,
181*5c51f124SMoriah Waterland 				char *a_key, char *a_object, int a_quiet,
182*5c51f124SMoriah Waterland 				int a_wait, long a_timeout, int a_exclusive,
183*5c51f124SMoriah Waterland 				char *a_altRoot, pid_t a_pid, zoneid_t a_zid);
184*5c51f124SMoriah Waterland static int		lock_release(int a_fd, char *a_key, char *a_object,
185*5c51f124SMoriah Waterland 				int a_quiet);
186*5c51f124SMoriah Waterland static int		lock_status(int a_fd, char *a_key, char *a_object,
187*5c51f124SMoriah Waterland 				int a_quiet);
188*5c51f124SMoriah Waterland 
189*5c51f124SMoriah Waterland /* local utility functions */
190*5c51f124SMoriah Waterland 
191*5c51f124SMoriah Waterland static int		_lockMatch(char *a_s1Lock, char *a_s2Lock);
192*5c51f124SMoriah Waterland static FINDLOCK_T	_findLock(LOCK_T *a_theLock, RECORDNUM_T *r_recordNum,
193*5c51f124SMoriah Waterland 				int a_fd, char *a_object, char *a_key);
194*5c51f124SMoriah Waterland static int		_decrementLockCount(int a_fd, LOCK_T *a_theLock);
195*5c51f124SMoriah Waterland static int		_addLock(char *r_key, int a_fd, char *a_object,
196*5c51f124SMoriah Waterland 				int a_exclusive, pid_t a_pid, zoneid_t a_zid);
197*5c51f124SMoriah Waterland static int		_incrementLockCount(int a_fd, LOCK_T *a_theLock);
198*5c51f124SMoriah Waterland static FINDLOCK_T	_lock_acquire(LOCK_T *a_lock, int a_fd, char *a_key,
199*5c51f124SMoriah Waterland 				char *a_object, int a_quiet, int a_exclusive,
200*5c51f124SMoriah Waterland 				pid_t a_pid, zoneid_t a_zid);
201*5c51f124SMoriah Waterland static char		*_getUniqueId(void);
202*5c51f124SMoriah Waterland static int		_openLockFile(char *a_root);
203*5c51f124SMoriah Waterland static void		sighup_handler(int a_signo);
204*5c51f124SMoriah Waterland static void		sigint_handler(int a_signo);
205*5c51f124SMoriah Waterland static boolean_t	_validateLock(int a_fd, LOCK_T *a_theLock, int a_quiet);
206*5c51f124SMoriah Waterland 
207*5c51f124SMoriah Waterland static int		signal_received = 0;
208*5c51f124SMoriah Waterland 
209*5c51f124SMoriah Waterland /*
210*5c51f124SMoriah Waterland  * main methods with external entry points
211*5c51f124SMoriah Waterland  */
212*5c51f124SMoriah Waterland 
213*5c51f124SMoriah Waterland /*
214*5c51f124SMoriah Waterland  * Name:	admin_lock
215*5c51f124SMoriah Waterland  * Synopsis:	main entry point for pkgadm "lock" subcommand
216*5c51f124SMoriah Waterland  * Description:	Control zone/package administrative locking
217*5c51f124SMoriah Waterland  * Returns: 0 on success, non-zero otherwise.
218*5c51f124SMoriah Waterland  */
219*5c51f124SMoriah Waterland 
220*5c51f124SMoriah Waterland int
221*5c51f124SMoriah Waterland admin_lock(int argc, char **argv)
222*5c51f124SMoriah Waterland {
223*5c51f124SMoriah Waterland 	FINDLOCK_T		tResult;
224*5c51f124SMoriah Waterland 	LOCK_T			theLock;
225*5c51f124SMoriah Waterland 	char			*RFlag = "/";	/* altRoot */
226*5c51f124SMoriah Waterland 	char			*endptr;
227*5c51f124SMoriah Waterland 	char			*kFlag = "";	/* key */
228*5c51f124SMoriah Waterland 	char			*oFlag = "";	/* object */
229*5c51f124SMoriah Waterland 	char			*p;
230*5c51f124SMoriah Waterland 	char			c;
231*5c51f124SMoriah Waterland 	int			aFlag = 0;	/* acquire lock */
232*5c51f124SMoriah Waterland 	int			eFlag = 0;	/* exclusive lock */
233*5c51f124SMoriah Waterland 	int			exclusive = 1;	/* exclusive vs shared lock */
234*5c51f124SMoriah Waterland 	int			fd;
235*5c51f124SMoriah Waterland 	int			qFlag = 0;	/* quiet */
236*5c51f124SMoriah Waterland 	int			rFlag = 0;	/* release lock */
237*5c51f124SMoriah Waterland 	int			result;
238*5c51f124SMoriah Waterland 	int			sFlag = 0;	/* shared lock */
239*5c51f124SMoriah Waterland 	int			tFlag = 0;	/* test comparison */
240*5c51f124SMoriah Waterland 	int			wFlag = 0;	/* wait */
241*5c51f124SMoriah Waterland 	long			WFlag = 0;	/* wait timeout */
242*5c51f124SMoriah Waterland 	pid_t			pFlag = 0;	/* process # */
243*5c51f124SMoriah Waterland 	struct sigaction	nact;
244*5c51f124SMoriah Waterland 	struct sigaction	oact;
245*5c51f124SMoriah Waterland 	void			(*funcSighup)();
246*5c51f124SMoriah Waterland 	void			(*funcSigint)();
247*5c51f124SMoriah Waterland 	zoneid_t		zFlag = -1;	/* zone i.d. */
248*5c51f124SMoriah Waterland 
249*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":aek:o:p:qrR:stwW:z:")) != EOF) {
250*5c51f124SMoriah Waterland 		switch (c) {
251*5c51f124SMoriah Waterland 		case 'a':	/* acquire lock */
252*5c51f124SMoriah Waterland 			aFlag++;
253*5c51f124SMoriah Waterland 			break;
254*5c51f124SMoriah Waterland 
255*5c51f124SMoriah Waterland 		case 'e':	/* exclusive lock */
256*5c51f124SMoriah Waterland 			eFlag++;
257*5c51f124SMoriah Waterland 			break;
258*5c51f124SMoriah Waterland 
259*5c51f124SMoriah Waterland 		case 'k':	/* lock-key */
260*5c51f124SMoriah Waterland 			kFlag = optarg;
261*5c51f124SMoriah Waterland 			if (strlen(optarg) > LOCK_KEY_MAXLEN) {
262*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_ERR,
263*5c51f124SMoriah Waterland 					MSG_LOCK_kARG_TOOLONG,
264*5c51f124SMoriah Waterland 					strlen(optarg), LOCK_KEY_MAXLEN);
265*5c51f124SMoriah Waterland 				return (1);
266*5c51f124SMoriah Waterland 			}
267*5c51f124SMoriah Waterland 			break;
268*5c51f124SMoriah Waterland 
269*5c51f124SMoriah Waterland 		case 'o':	/* object */
270*5c51f124SMoriah Waterland 			oFlag = optarg;
271*5c51f124SMoriah Waterland 			if (strlen(optarg) > LOCK_OBJECT_MAXLEN) {
272*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_ERR,
273*5c51f124SMoriah Waterland 					MSG_LOCK_oARG_TOOLONG,
274*5c51f124SMoriah Waterland 					strlen(optarg), LOCK_OBJECT_MAXLEN);
275*5c51f124SMoriah Waterland 				return (1);
276*5c51f124SMoriah Waterland 			}
277*5c51f124SMoriah Waterland 			break;
278*5c51f124SMoriah Waterland 
279*5c51f124SMoriah Waterland 		case 'p':	/* process i.d. */
280*5c51f124SMoriah Waterland 			errno = 0;
281*5c51f124SMoriah Waterland 			endptr = 0;
282*5c51f124SMoriah Waterland 			pFlag = strtol(optarg, &endptr, 10);
283*5c51f124SMoriah Waterland 			if ((endptr != (char *)NULL) && (*endptr != '\0')) {
284*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_ERR, MSG_LOCK_pFLAG_BADINT,
285*5c51f124SMoriah Waterland 							optarg, *endptr);
286*5c51f124SMoriah Waterland 				return (1);
287*5c51f124SMoriah Waterland 			}
288*5c51f124SMoriah Waterland 			if ((pFlag == 0) && (errno != 0)) {
289*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_ERR,
290*5c51f124SMoriah Waterland 					MSG_LOCK_pFLAG_ERROR,
291*5c51f124SMoriah Waterland 					optarg,  strerror(errno));
292*5c51f124SMoriah Waterland 				return (1);
293*5c51f124SMoriah Waterland 			}
294*5c51f124SMoriah Waterland 			break;
295*5c51f124SMoriah Waterland 
296*5c51f124SMoriah Waterland 		case 'q':	/* quiet */
297*5c51f124SMoriah Waterland 			qFlag++;
298*5c51f124SMoriah Waterland 			break;
299*5c51f124SMoriah Waterland 
300*5c51f124SMoriah Waterland 		case 'r':	/* release lock */
301*5c51f124SMoriah Waterland 			rFlag++;
302*5c51f124SMoriah Waterland 			break;
303*5c51f124SMoriah Waterland 
304*5c51f124SMoriah Waterland 		case 'R':	/* alternative root */
305*5c51f124SMoriah Waterland 			/* if root directory is not absolute path, error */
306*5c51f124SMoriah Waterland 			if (*optarg != '/') {
307*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_ERR,
308*5c51f124SMoriah Waterland 					MSG_LOCK_RARG_NOT_ABSOLUTE, optarg);
309*5c51f124SMoriah Waterland 				return (1);
310*5c51f124SMoriah Waterland 			}
311*5c51f124SMoriah Waterland 
312*5c51f124SMoriah Waterland 			/* if root directory does not exist, create it */
313*5c51f124SMoriah Waterland 			if (access(optarg, F_OK) != 0) {
314*5c51f124SMoriah Waterland 
315*5c51f124SMoriah Waterland 				/* create top level root directory */
316*5c51f124SMoriah Waterland 				if (mkdirp(optarg, 0755) != 0) {
317*5c51f124SMoriah Waterland 					log_msg(LOG_MSG_ERR,
318*5c51f124SMoriah Waterland 						MSG_LOCK_ALTROOT_CANTCREATE,
319*5c51f124SMoriah Waterland 						optarg, strerror(errno));
320*5c51f124SMoriah Waterland 					return (1);
321*5c51f124SMoriah Waterland 				}
322*5c51f124SMoriah Waterland 			}
323*5c51f124SMoriah Waterland 
324*5c51f124SMoriah Waterland 			/* if $ALTROOT/tmp directory does not exist create it */
325*5c51f124SMoriah Waterland 			p = pkgstrPrintf("%s/tmp", optarg);
326*5c51f124SMoriah Waterland 			if (access(p, F_OK) != 0) {
327*5c51f124SMoriah Waterland 
328*5c51f124SMoriah Waterland 				/* create $ALTROOT/tmp directory */
329*5c51f124SMoriah Waterland 				if (mkdirp(p, 0777) != 0) {
330*5c51f124SMoriah Waterland 					log_msg(LOG_MSG_ERR,
331*5c51f124SMoriah Waterland 						MSG_LOCK_ALTROOT_CANTCREATE,
332*5c51f124SMoriah Waterland 						p, strerror(errno));
333*5c51f124SMoriah Waterland 					return (1);
334*5c51f124SMoriah Waterland 				}
335*5c51f124SMoriah Waterland 			}
336*5c51f124SMoriah Waterland 
337*5c51f124SMoriah Waterland 			/* if $ALTROOT/tmp directory cannot be created, exit */
338*5c51f124SMoriah Waterland 			if (access(p, F_OK) != 0) {
339*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_ERR, MSG_LOCK_ALTROOT_NONEXIST,
340*5c51f124SMoriah Waterland 					optarg, strerror(errno));
341*5c51f124SMoriah Waterland 				return (1);
342*5c51f124SMoriah Waterland 			}
343*5c51f124SMoriah Waterland 
344*5c51f124SMoriah Waterland 			(void) free(p);
345*5c51f124SMoriah Waterland 
346*5c51f124SMoriah Waterland 			RFlag = optarg;
347*5c51f124SMoriah Waterland 			break;
348*5c51f124SMoriah Waterland 
349*5c51f124SMoriah Waterland 		case 's':	/* shared */
350*5c51f124SMoriah Waterland 			sFlag++;
351*5c51f124SMoriah Waterland 			break;
352*5c51f124SMoriah Waterland 
353*5c51f124SMoriah Waterland 		case 't':	/* test comparison */
354*5c51f124SMoriah Waterland 			tFlag++;
355*5c51f124SMoriah Waterland 			break;
356*5c51f124SMoriah Waterland 
357*5c51f124SMoriah Waterland 		case 'w':	/* wait */
358*5c51f124SMoriah Waterland 			wFlag++;
359*5c51f124SMoriah Waterland 			break;
360*5c51f124SMoriah Waterland 
361*5c51f124SMoriah Waterland 		case 'W':	/* wait with timeout */
362*5c51f124SMoriah Waterland 			errno = 0;
363*5c51f124SMoriah Waterland 			endptr = 0;
364*5c51f124SMoriah Waterland 			WFlag = strtol(optarg, &endptr, 10);
365*5c51f124SMoriah Waterland 			if ((endptr != (char *)NULL) && (*endptr != '\0')) {
366*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_ERR, MSG_LOCK_WFLAG_BADINT,
367*5c51f124SMoriah Waterland 							optarg, *endptr);
368*5c51f124SMoriah Waterland 				return (1);
369*5c51f124SMoriah Waterland 			}
370*5c51f124SMoriah Waterland 			if ((WFlag == 0) && (errno != 0)) {
371*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_ERR,
372*5c51f124SMoriah Waterland 					MSG_LOCK_WFLAG_ERROR,
373*5c51f124SMoriah Waterland 					optarg,  strerror(errno));
374*5c51f124SMoriah Waterland 				return (1);
375*5c51f124SMoriah Waterland 			}
376*5c51f124SMoriah Waterland 			wFlag++;
377*5c51f124SMoriah Waterland 			break;
378*5c51f124SMoriah Waterland 
379*5c51f124SMoriah Waterland 		case 'z':	/* zone i.d. */
380*5c51f124SMoriah Waterland 			errno = 0;
381*5c51f124SMoriah Waterland 			endptr = 0;
382*5c51f124SMoriah Waterland 			zFlag = strtol(optarg, &endptr, 10);
383*5c51f124SMoriah Waterland 			if ((endptr != (char *)NULL) && (*endptr != '\0')) {
384*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_ERR, MSG_LOCK_zFLAG_BADINT,
385*5c51f124SMoriah Waterland 							optarg, *endptr);
386*5c51f124SMoriah Waterland 				return (1);
387*5c51f124SMoriah Waterland 			}
388*5c51f124SMoriah Waterland 			if ((zFlag == 0) && (errno != 0)) {
389*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_ERR,
390*5c51f124SMoriah Waterland 					MSG_LOCK_zFLAG_ERROR,
391*5c51f124SMoriah Waterland 					optarg,  strerror(errno));
392*5c51f124SMoriah Waterland 				return (1);
393*5c51f124SMoriah Waterland 			}
394*5c51f124SMoriah Waterland 			break;
395*5c51f124SMoriah Waterland 
396*5c51f124SMoriah Waterland 		case ':':
397*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_ERR, MSG_MISSING_OPERAND, optopt);
398*5c51f124SMoriah Waterland 			/* LINTED fallthrough on case statement */
399*5c51f124SMoriah Waterland 		case '?':
400*5c51f124SMoriah Waterland 
401*5c51f124SMoriah Waterland 		default:
402*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_ERR, MSG_USAGE);
403*5c51f124SMoriah Waterland 			return (1);
404*5c51f124SMoriah Waterland 		}
405*5c51f124SMoriah Waterland 	}
406*5c51f124SMoriah Waterland 
407*5c51f124SMoriah Waterland 	/*
408*5c51f124SMoriah Waterland 	 * validate arguments
409*5c51f124SMoriah Waterland 	 */
410*5c51f124SMoriah Waterland 
411*5c51f124SMoriah Waterland 	/* if -t option is specified, override all other options */
412*5c51f124SMoriah Waterland 
413*5c51f124SMoriah Waterland 	if (tFlag) {
414*5c51f124SMoriah Waterland 		int	rs;
415*5c51f124SMoriah Waterland 		int	rx;
416*5c51f124SMoriah Waterland 		int	a;
417*5c51f124SMoriah Waterland 
418*5c51f124SMoriah Waterland 		/* only 2 or 3 args are valid */
419*5c51f124SMoriah Waterland 
420*5c51f124SMoriah Waterland 		a = argc-optind;
421*5c51f124SMoriah Waterland 		if ((a < 2) || (a > 3)) {
422*5c51f124SMoriah Waterland 			(void) fprintf(stderr, MSG_T_OPTION_ARGS, argc-optind);
423*5c51f124SMoriah Waterland 			return (1);
424*5c51f124SMoriah Waterland 		}
425*5c51f124SMoriah Waterland 
426*5c51f124SMoriah Waterland 		/* if 3rd argument given, it is return value to check */
427*5c51f124SMoriah Waterland 
428*5c51f124SMoriah Waterland 		if (a == 3) {
429*5c51f124SMoriah Waterland 			rs = atoi(argv[optind+2]);
430*5c51f124SMoriah Waterland 		}
431*5c51f124SMoriah Waterland 		rx = _lockMatch(argv[optind+0], argv[optind+1]);
432*5c51f124SMoriah Waterland 
433*5c51f124SMoriah Waterland 		/* if 3rd argument not given, code to check is code returned */
434*5c51f124SMoriah Waterland 
435*5c51f124SMoriah Waterland 		if (a == 2) {
436*5c51f124SMoriah Waterland 			rs = rx;
437*5c51f124SMoriah Waterland 		}
438*5c51f124SMoriah Waterland 
439*5c51f124SMoriah Waterland 		/* report results */
440*5c51f124SMoriah Waterland 
441*5c51f124SMoriah Waterland 		if (a == 2) {
442*5c51f124SMoriah Waterland 			(void) fprintf(stderr, MSG_T_RESULT_TWO,
443*5c51f124SMoriah Waterland 				rx, argv[optind+0], argv[optind+1]);
444*5c51f124SMoriah Waterland 			return (rx);
445*5c51f124SMoriah Waterland 		}
446*5c51f124SMoriah Waterland 
447*5c51f124SMoriah Waterland 		if (rx != rs) {
448*5c51f124SMoriah Waterland 			(void) fprintf(stderr, MSG_T_RESULT_THREE,
449*5c51f124SMoriah Waterland 				rs, rx, argv[optind+0], argv[optind+1]);
450*5c51f124SMoriah Waterland 		}
451*5c51f124SMoriah Waterland 
452*5c51f124SMoriah Waterland 		/* always successful */
453*5c51f124SMoriah Waterland 
454*5c51f124SMoriah Waterland 		return (rx == rs ? 0 : 1);
455*5c51f124SMoriah Waterland 	}
456*5c51f124SMoriah Waterland 
457*5c51f124SMoriah Waterland 	/* must be no non-option arguments left */
458*5c51f124SMoriah Waterland 
459*5c51f124SMoriah Waterland 	if ((argc-optind) > 0) {
460*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_USAGE);
461*5c51f124SMoriah Waterland 		return (1);
462*5c51f124SMoriah Waterland 	}
463*5c51f124SMoriah Waterland 
464*5c51f124SMoriah Waterland 	/* -a and -r cannot be used together */
465*5c51f124SMoriah Waterland 
466*5c51f124SMoriah Waterland 	if (aFlag && rFlag) {
467*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_ar_TOGETHER);
468*5c51f124SMoriah Waterland 		return (1);
469*5c51f124SMoriah Waterland 	}
470*5c51f124SMoriah Waterland 
471*5c51f124SMoriah Waterland 	/* -e and -s cannot be used together */
472*5c51f124SMoriah Waterland 
473*5c51f124SMoriah Waterland 	if (eFlag && sFlag) {
474*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_es_TOGETHER);
475*5c51f124SMoriah Waterland 		return (1);
476*5c51f124SMoriah Waterland 	}
477*5c51f124SMoriah Waterland 
478*5c51f124SMoriah Waterland 	/* -e can only be used if -a is used */
479*5c51f124SMoriah Waterland 
480*5c51f124SMoriah Waterland 	if (!aFlag && eFlag) {
481*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_e_without_a);
482*5c51f124SMoriah Waterland 		return (1);
483*5c51f124SMoriah Waterland 	}
484*5c51f124SMoriah Waterland 
485*5c51f124SMoriah Waterland 	/* -s can only be used if -a is used */
486*5c51f124SMoriah Waterland 
487*5c51f124SMoriah Waterland 	if (!aFlag && sFlag) {
488*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_s_without_a);
489*5c51f124SMoriah Waterland 		return (1);
490*5c51f124SMoriah Waterland 	}
491*5c51f124SMoriah Waterland 
492*5c51f124SMoriah Waterland 	/*
493*5c51f124SMoriah Waterland 	 * perform the requested operation
494*5c51f124SMoriah Waterland 	 */
495*5c51f124SMoriah Waterland 
496*5c51f124SMoriah Waterland 	/*
497*5c51f124SMoriah Waterland 	 * hook SIGINT and SIGHUP interrupts into quit.c's trap handler
498*5c51f124SMoriah Waterland 	 */
499*5c51f124SMoriah Waterland 
500*5c51f124SMoriah Waterland 	/* hold SIGINT/SIGHUP interrupts */
501*5c51f124SMoriah Waterland 
502*5c51f124SMoriah Waterland 	(void) sighold(SIGHUP);
503*5c51f124SMoriah Waterland 	(void) sighold(SIGINT);
504*5c51f124SMoriah Waterland 
505*5c51f124SMoriah Waterland 	/* connect sigint_handler() to SIGINT */
506*5c51f124SMoriah Waterland 
507*5c51f124SMoriah Waterland 	nact.sa_handler = sigint_handler;
508*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
509*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
510*5c51f124SMoriah Waterland 
511*5c51f124SMoriah Waterland 	if (sigaction(SIGINT, &nact, &oact) < 0) {
512*5c51f124SMoriah Waterland 		funcSigint = SIG_DFL;
513*5c51f124SMoriah Waterland 	} else {
514*5c51f124SMoriah Waterland 		funcSigint = oact.sa_handler;
515*5c51f124SMoriah Waterland 	}
516*5c51f124SMoriah Waterland 
517*5c51f124SMoriah Waterland 	/* connect sighupt_handler() to SIGHUP */
518*5c51f124SMoriah Waterland 
519*5c51f124SMoriah Waterland 	nact.sa_handler = sighup_handler;
520*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
521*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
522*5c51f124SMoriah Waterland 
523*5c51f124SMoriah Waterland 	if (sigaction(SIGHUP, &nact, &oact) < 0) {
524*5c51f124SMoriah Waterland 		funcSighup = SIG_DFL;
525*5c51f124SMoriah Waterland 	} else {
526*5c51f124SMoriah Waterland 		funcSighup = oact.sa_handler;
527*5c51f124SMoriah Waterland 	}
528*5c51f124SMoriah Waterland 
529*5c51f124SMoriah Waterland 	/* release hold on signals */
530*5c51f124SMoriah Waterland 
531*5c51f124SMoriah Waterland 	(void) sigrelse(SIGHUP);
532*5c51f124SMoriah Waterland 	(void) sigrelse(SIGINT);
533*5c51f124SMoriah Waterland 
534*5c51f124SMoriah Waterland 	/* open the lock file */
535*5c51f124SMoriah Waterland 
536*5c51f124SMoriah Waterland 	fd = _openLockFile(RFlag);
537*5c51f124SMoriah Waterland 	if (fd < 0) {
538*5c51f124SMoriah Waterland 		return (1);
539*5c51f124SMoriah Waterland 	}
540*5c51f124SMoriah Waterland 
541*5c51f124SMoriah Waterland 	if (aFlag) {
542*5c51f124SMoriah Waterland 		/* set "exclusive" mode based on -e/-s flag used */
543*5c51f124SMoriah Waterland 
544*5c51f124SMoriah Waterland 		if (sFlag) {
545*5c51f124SMoriah Waterland 			exclusive = 0;
546*5c51f124SMoriah Waterland 		} else if (eFlag) {
547*5c51f124SMoriah Waterland 			exclusive = 1;
548*5c51f124SMoriah Waterland 		}
549*5c51f124SMoriah Waterland 
550*5c51f124SMoriah Waterland 		/* acquire lock */
551*5c51f124SMoriah Waterland 
552*5c51f124SMoriah Waterland 		tResult = lock_acquire(&theLock, &fd, RFlag, kFlag, oFlag,
553*5c51f124SMoriah Waterland 			qFlag, wFlag, WFlag, exclusive, RFlag, pFlag, zFlag);
554*5c51f124SMoriah Waterland 
555*5c51f124SMoriah Waterland 		switch (tResult) {
556*5c51f124SMoriah Waterland 		case FINDLOCK_LOCKACQUIRED:
557*5c51f124SMoriah Waterland 			(void) fprintf(stdout, "%s\n",
558*5c51f124SMoriah Waterland 				theLock._lrLock.lockKey);
559*5c51f124SMoriah Waterland 			result = 0;
560*5c51f124SMoriah Waterland 			break;
561*5c51f124SMoriah Waterland 		case FINDLOCK_LOCKED:
562*5c51f124SMoriah Waterland 			(void) fprintf(stdout, "%s\n",
563*5c51f124SMoriah Waterland 				theLock._lrLock.lockObject);
564*5c51f124SMoriah Waterland 			result = 1;
565*5c51f124SMoriah Waterland 			break;
566*5c51f124SMoriah Waterland 		default:
567*5c51f124SMoriah Waterland 			result = 1;
568*5c51f124SMoriah Waterland 			break;
569*5c51f124SMoriah Waterland 		}
570*5c51f124SMoriah Waterland 
571*5c51f124SMoriah Waterland 	} else if (rFlag) {
572*5c51f124SMoriah Waterland 		/* release lock */
573*5c51f124SMoriah Waterland 		result = lock_release(fd, kFlag, oFlag, qFlag);
574*5c51f124SMoriah Waterland 	} else {
575*5c51f124SMoriah Waterland 		/* lock status */
576*5c51f124SMoriah Waterland 		result = lock_status(fd, kFlag, oFlag, qFlag);
577*5c51f124SMoriah Waterland 	}
578*5c51f124SMoriah Waterland 
579*5c51f124SMoriah Waterland 	/* close the lock file */
580*5c51f124SMoriah Waterland 
581*5c51f124SMoriah Waterland 	(void) close(fd);
582*5c51f124SMoriah Waterland 
583*5c51f124SMoriah Waterland 	/* return results of operation */
584*5c51f124SMoriah Waterland 
585*5c51f124SMoriah Waterland 	return (result);
586*5c51f124SMoriah Waterland }
587*5c51f124SMoriah Waterland 
588*5c51f124SMoriah Waterland /*
589*5c51f124SMoriah Waterland  * local main function implementation methods
590*5c51f124SMoriah Waterland  */
591*5c51f124SMoriah Waterland 
592*5c51f124SMoriah Waterland /*
593*5c51f124SMoriah Waterland  * Name:	lock_acquire
594*5c51f124SMoriah Waterland  * Description:	implement lock acquisition implementing the wait/timeouts
595*5c51f124SMoriah Waterland  *		Calls _lock_acquire to attempt lock acquisition.
596*5c51f124SMoriah Waterland  * Arguments:
597*5c51f124SMoriah Waterland  *	a_theLock - lock object filled with contents of existing lock
598*5c51f124SMoriah Waterland  *	a_fd - file descriptor opened on the lock file
599*5c51f124SMoriah Waterland  *	a_root - root of file system to manipulate locks on
600*5c51f124SMoriah Waterland  *	a_key - key associated with lock to acquire
601*5c51f124SMoriah Waterland  *	a_object - object associated with lock to acquire
602*5c51f124SMoriah Waterland  *	a_wait - wait if lock cannot be acquired flag:
603*5c51f124SMoriah Waterland  *			== 0 - do not wait
604*5c51f124SMoriah Waterland  *			!= 0 - wait
605*5c51f124SMoriah Waterland  *	a_timeout - timeout if waiting to acquire busy lock:
606*5c51f124SMoriah Waterland  *			== 0 - no timeout (wait forever)
607*5c51f124SMoriah Waterland  *			!= 0 - max # seconds to wait to acquire busy lock
608*5c51f124SMoriah Waterland  *	a_quiet - quiet mode enabled flag
609*5c51f124SMoriah Waterland  *	a_exclusive - exclusive/shared lock flag
610*5c51f124SMoriah Waterland  *	a_pid - if != 0 process i.d. to associate with this lock
611*5c51f124SMoriah Waterland  *	a_zid - if >= 0 - zone i.d. to associate with this lock
612*5c51f124SMoriah Waterland  * Returns: int
613*5c51f124SMoriah Waterland  *		== 0 - successful
614*5c51f124SMoriah Waterland  *		!= 0 - not successful
615*5c51f124SMoriah Waterland  */
616*5c51f124SMoriah Waterland 
617*5c51f124SMoriah Waterland static FINDLOCK_T
618*5c51f124SMoriah Waterland lock_acquire(LOCK_T *a_theLock, int *a_fd, char *a_root, char *a_key,
619*5c51f124SMoriah Waterland 	char *a_object, int a_quiet, int a_wait, long a_timeout,
620*5c51f124SMoriah Waterland 	int a_exclusive, char *a_altRoot, pid_t a_pid, zoneid_t a_zid)
621*5c51f124SMoriah Waterland {
622*5c51f124SMoriah Waterland 	int		notified = 0;
623*5c51f124SMoriah Waterland 	FINDLOCK_T	result;
624*5c51f124SMoriah Waterland 	time_t		timeout;
625*5c51f124SMoriah Waterland 	int		closeOnExit = 0;
626*5c51f124SMoriah Waterland 
627*5c51f124SMoriah Waterland 	/* reset the lock */
628*5c51f124SMoriah Waterland 
629*5c51f124SMoriah Waterland 	bzero(a_theLock, sizeof (LOCK_T));
630*5c51f124SMoriah Waterland 
631*5c51f124SMoriah Waterland 	/* open file if not open */
632*5c51f124SMoriah Waterland 
633*5c51f124SMoriah Waterland 	if ((*a_fd) < 0) {
634*5c51f124SMoriah Waterland 		(*a_fd) = _openLockFile(a_altRoot);
635*5c51f124SMoriah Waterland 		if ((*a_fd) < 0) {
636*5c51f124SMoriah Waterland 			return (FINDLOCK_ERROR);
637*5c51f124SMoriah Waterland 		}
638*5c51f124SMoriah Waterland 		closeOnExit++;
639*5c51f124SMoriah Waterland 	}
640*5c51f124SMoriah Waterland 
641*5c51f124SMoriah Waterland 	/* compute time after which acquire times out */
642*5c51f124SMoriah Waterland 
643*5c51f124SMoriah Waterland 	timeout = time((time_t *)NULL) + a_timeout;
644*5c51f124SMoriah Waterland 
645*5c51f124SMoriah Waterland 	for (;;) {
646*5c51f124SMoriah Waterland 		time_t	curtime;
647*5c51f124SMoriah Waterland 
648*5c51f124SMoriah Waterland 		/* attempt to aquire the lock */
649*5c51f124SMoriah Waterland 
650*5c51f124SMoriah Waterland 		result = _lock_acquire(a_theLock, *a_fd, a_key, a_object,
651*5c51f124SMoriah Waterland 				a_quiet, a_exclusive, a_pid, a_zid);
652*5c51f124SMoriah Waterland 
653*5c51f124SMoriah Waterland 		/* return result if any result other than object is locked */
654*5c51f124SMoriah Waterland 
655*5c51f124SMoriah Waterland 		switch (result) {
656*5c51f124SMoriah Waterland 		case FINDLOCK_LOCKACQUIRED:
657*5c51f124SMoriah Waterland 
658*5c51f124SMoriah Waterland 			/* close lock file if opened in this function */
659*5c51f124SMoriah Waterland 
660*5c51f124SMoriah Waterland 			if (closeOnExit) {
661*5c51f124SMoriah Waterland 				(void) close(*a_fd);
662*5c51f124SMoriah Waterland 				*a_fd = -1;
663*5c51f124SMoriah Waterland 			}
664*5c51f124SMoriah Waterland 
665*5c51f124SMoriah Waterland 			return (FINDLOCK_LOCKACQUIRED);
666*5c51f124SMoriah Waterland 
667*5c51f124SMoriah Waterland 		case FINDLOCK_FOUND:
668*5c51f124SMoriah Waterland 		case FINDLOCK_NOTFOUND:
669*5c51f124SMoriah Waterland 		case FINDLOCK_KEYMISMATCH:
670*5c51f124SMoriah Waterland 		case FINDLOCK_NOTLOCKED:
671*5c51f124SMoriah Waterland 		case FINDLOCK_ERROR:
672*5c51f124SMoriah Waterland 		default:
673*5c51f124SMoriah Waterland 			/* close lock file if opened in this function */
674*5c51f124SMoriah Waterland 
675*5c51f124SMoriah Waterland 			if (closeOnExit) {
676*5c51f124SMoriah Waterland 				(void) close(*a_fd);
677*5c51f124SMoriah Waterland 				*a_fd = -1;
678*5c51f124SMoriah Waterland 			}
679*5c51f124SMoriah Waterland 
680*5c51f124SMoriah Waterland 			return (result);
681*5c51f124SMoriah Waterland 
682*5c51f124SMoriah Waterland 		case FINDLOCK_LOCKED:
683*5c51f124SMoriah Waterland 			;
684*5c51f124SMoriah Waterland 			/* FALLTHROUGH */
685*5c51f124SMoriah Waterland 		}
686*5c51f124SMoriah Waterland 
687*5c51f124SMoriah Waterland 		/*
688*5c51f124SMoriah Waterland 		 * object locked OR SIGINT/SIGHUP interrupt received;
689*5c51f124SMoriah Waterland 		 * return error if not waiting for lock OR signal received
690*5c51f124SMoriah Waterland 		 */
691*5c51f124SMoriah Waterland 
692*5c51f124SMoriah Waterland 		if ((a_wait == 0) || (signal_received != 0)) {
693*5c51f124SMoriah Waterland 			log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR,
694*5c51f124SMoriah Waterland 				MSG_LOCK_ACQUIRE_BUSY_FIRST,
695*5c51f124SMoriah Waterland 				a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR,
696*5c51f124SMoriah Waterland 				a_object, a_key,
697*5c51f124SMoriah Waterland 				a_theLock->_lrLock.lockObject,
698*5c51f124SMoriah Waterland 				a_theLock->_lrLock.lockExclusive ?
699*5c51f124SMoriah Waterland 						MSG_LOCK_EXC : MSG_LOCK_SHR,
700*5c51f124SMoriah Waterland 				a_theLock->_lrLock.lockExclusive !=
701*5c51f124SMoriah Waterland 					a_exclusive ? "" :
702*5c51f124SMoriah Waterland 					MSG_LOCK_ACQUIRE_BUSY_ADDITIONAL);
703*5c51f124SMoriah Waterland 
704*5c51f124SMoriah Waterland 			/* close lock file if opened in this function */
705*5c51f124SMoriah Waterland 
706*5c51f124SMoriah Waterland 			if (closeOnExit) {
707*5c51f124SMoriah Waterland 				(void) close(*a_fd);
708*5c51f124SMoriah Waterland 				*a_fd = -1;
709*5c51f124SMoriah Waterland 			}
710*5c51f124SMoriah Waterland 
711*5c51f124SMoriah Waterland 			return (FINDLOCK_LOCKED);
712*5c51f124SMoriah Waterland 		}
713*5c51f124SMoriah Waterland 
714*5c51f124SMoriah Waterland 		/* waiting for lock - if timeout specified see if time left */
715*5c51f124SMoriah Waterland 
716*5c51f124SMoriah Waterland 		if (a_timeout > 0) {
717*5c51f124SMoriah Waterland 			curtime = time((time_t *)NULL);
718*5c51f124SMoriah Waterland 			if (curtime > timeout) {
719*5c51f124SMoriah Waterland 				log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR,
720*5c51f124SMoriah Waterland 					MSG_LOCK_ACQUIRE_TIMEDOUT,
721*5c51f124SMoriah Waterland 					a_exclusive ?
722*5c51f124SMoriah Waterland 						MSG_LOCK_EXC : MSG_LOCK_SHR,
723*5c51f124SMoriah Waterland 					a_object, a_key);
724*5c51f124SMoriah Waterland 
725*5c51f124SMoriah Waterland 				/* close lock file if opened in this function */
726*5c51f124SMoriah Waterland 
727*5c51f124SMoriah Waterland 				if (closeOnExit) {
728*5c51f124SMoriah Waterland 					(void) close(*a_fd);
729*5c51f124SMoriah Waterland 					*a_fd = -1;
730*5c51f124SMoriah Waterland 				}
731*5c51f124SMoriah Waterland 
732*5c51f124SMoriah Waterland 				return (FINDLOCK_ERROR);
733*5c51f124SMoriah Waterland 			}
734*5c51f124SMoriah Waterland 		}
735*5c51f124SMoriah Waterland 
736*5c51f124SMoriah Waterland 		/*
737*5c51f124SMoriah Waterland 		 * waiting to aquire lock:
738*5c51f124SMoriah Waterland 		 * - notify waiting (one time only)
739*5c51f124SMoriah Waterland 		 * - close lock file
740*5c51f124SMoriah Waterland 		 * - sleep
741*5c51f124SMoriah Waterland 		 * - open lock file
742*5c51f124SMoriah Waterland 		 * - try again
743*5c51f124SMoriah Waterland 		 */
744*5c51f124SMoriah Waterland 
745*5c51f124SMoriah Waterland 		/* notify once */
746*5c51f124SMoriah Waterland 
747*5c51f124SMoriah Waterland 		if (notified++ == 0) {
748*5c51f124SMoriah Waterland 			log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_WRN,
749*5c51f124SMoriah Waterland 				MSG_LOCK_ACQUIRE_WAITING,
750*5c51f124SMoriah Waterland 				a_object);
751*5c51f124SMoriah Waterland 		}
752*5c51f124SMoriah Waterland 
753*5c51f124SMoriah Waterland 		/* close lock file */
754*5c51f124SMoriah Waterland 
755*5c51f124SMoriah Waterland 		(void) close(*a_fd);
756*5c51f124SMoriah Waterland 
757*5c51f124SMoriah Waterland 		/* wait (sleep) */
758*5c51f124SMoriah Waterland 
759*5c51f124SMoriah Waterland 		(void) sleep(LOCK_SLEEP_INTERVAL);
760*5c51f124SMoriah Waterland 
761*5c51f124SMoriah Waterland 		/* open the lock file and try again */
762*5c51f124SMoriah Waterland 
763*5c51f124SMoriah Waterland 		*a_fd = _openLockFile(a_root);
764*5c51f124SMoriah Waterland 		if (*a_fd < 0) {
765*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_ERR, MSG_LOCK_ACQUIRE_REOPEN_FAILED,
766*5c51f124SMoriah Waterland 				a_object);
767*5c51f124SMoriah Waterland 
768*5c51f124SMoriah Waterland 			/* close lock file if opened in this function */
769*5c51f124SMoriah Waterland 
770*5c51f124SMoriah Waterland 			if (closeOnExit) {
771*5c51f124SMoriah Waterland 				(void) close(*a_fd);
772*5c51f124SMoriah Waterland 				*a_fd = -1;
773*5c51f124SMoriah Waterland 			}
774*5c51f124SMoriah Waterland 
775*5c51f124SMoriah Waterland 			return (FINDLOCK_ERROR);
776*5c51f124SMoriah Waterland 		}
777*5c51f124SMoriah Waterland 	}
778*5c51f124SMoriah Waterland }
779*5c51f124SMoriah Waterland 
780*5c51f124SMoriah Waterland /*
781*5c51f124SMoriah Waterland  * Name:	lock_release
782*5c51f124SMoriah Waterland  * Description:	implement lock release
783*5c51f124SMoriah Waterland  * Arguments:
784*5c51f124SMoriah Waterland  *	a_fd - file descriptor opened on the lock file
785*5c51f124SMoriah Waterland  *	a_key - key associated with lock to release
786*5c51f124SMoriah Waterland  *	a_object - object associated with lock to release
787*5c51f124SMoriah Waterland  *	a_quiet - quiet mode enabled flag
788*5c51f124SMoriah Waterland  * Returns: int
789*5c51f124SMoriah Waterland  *		== 0 - successful
790*5c51f124SMoriah Waterland  *		!= 0 - not successful
791*5c51f124SMoriah Waterland  */
792*5c51f124SMoriah Waterland 
793*5c51f124SMoriah Waterland static int
794*5c51f124SMoriah Waterland lock_release(int a_fd, char *a_key, char *a_object, int a_quiet)
795*5c51f124SMoriah Waterland {
796*5c51f124SMoriah Waterland 	RECORDNUM_T	recordNum;
797*5c51f124SMoriah Waterland 	LOCK_T		theLock;
798*5c51f124SMoriah Waterland 	FINDLOCK_T	result;
799*5c51f124SMoriah Waterland 
800*5c51f124SMoriah Waterland 	/* entry debugging info */
801*5c51f124SMoriah Waterland 
802*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_RELEASE_ENTRY,
803*5c51f124SMoriah Waterland 		a_key, a_object, a_quiet);
804*5c51f124SMoriah Waterland 
805*5c51f124SMoriah Waterland 	/* find the lock to be released */
806*5c51f124SMoriah Waterland 
807*5c51f124SMoriah Waterland 	result = _findLock(&theLock, &recordNum, a_fd, a_object, a_key);
808*5c51f124SMoriah Waterland 
809*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_RELEASE_FINDRESULT,
810*5c51f124SMoriah Waterland 		result, recordNum);
811*5c51f124SMoriah Waterland 
812*5c51f124SMoriah Waterland 	/* determine how to release the lock if found */
813*5c51f124SMoriah Waterland 
814*5c51f124SMoriah Waterland 	switch (result) {
815*5c51f124SMoriah Waterland 		/*
816*5c51f124SMoriah Waterland 		 * object is not locked but a key was specified
817*5c51f124SMoriah Waterland 		 */
818*5c51f124SMoriah Waterland 		case FINDLOCK_NOTLOCKED:
819*5c51f124SMoriah Waterland 			log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR,
820*5c51f124SMoriah Waterland 				MSG_LOCK_RELEASE_NOTLOCKED,
821*5c51f124SMoriah Waterland 				a_object, a_key);
822*5c51f124SMoriah Waterland 			return (result);
823*5c51f124SMoriah Waterland 
824*5c51f124SMoriah Waterland 		/*
825*5c51f124SMoriah Waterland 		 * object is locked and no matching key was specified
826*5c51f124SMoriah Waterland 		 */
827*5c51f124SMoriah Waterland 		case FINDLOCK_LOCKED:
828*5c51f124SMoriah Waterland 			log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR,
829*5c51f124SMoriah Waterland 				MSG_LOCK_RELEASE_LOCKED,
830*5c51f124SMoriah Waterland 				a_object, a_key);
831*5c51f124SMoriah Waterland 			return (result);
832*5c51f124SMoriah Waterland 
833*5c51f124SMoriah Waterland 		/*
834*5c51f124SMoriah Waterland 		 * object is not locked
835*5c51f124SMoriah Waterland 		 */
836*5c51f124SMoriah Waterland 		case FINDLOCK_NOTFOUND:
837*5c51f124SMoriah Waterland 			log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR,
838*5c51f124SMoriah Waterland 				MSG_LOCK_RELEASE_NOTFOUND,
839*5c51f124SMoriah Waterland 				a_object, a_key);
840*5c51f124SMoriah Waterland 			return (result);
841*5c51f124SMoriah Waterland 
842*5c51f124SMoriah Waterland 		/*
843*5c51f124SMoriah Waterland 		 * object is locked and specified key does not match
844*5c51f124SMoriah Waterland 		 */
845*5c51f124SMoriah Waterland 		case FINDLOCK_KEYMISMATCH:
846*5c51f124SMoriah Waterland 			log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR,
847*5c51f124SMoriah Waterland 				MSG_LOCK_RELEASE_KEYMISMATCH,
848*5c51f124SMoriah Waterland 				a_object);
849*5c51f124SMoriah Waterland 			return (result);
850*5c51f124SMoriah Waterland 
851*5c51f124SMoriah Waterland 		/*
852*5c51f124SMoriah Waterland 		 * error determining if object is locked
853*5c51f124SMoriah Waterland 		 */
854*5c51f124SMoriah Waterland 		case FINDLOCK_ERROR:
855*5c51f124SMoriah Waterland 			log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR,
856*5c51f124SMoriah Waterland 				MSG_LOCK_RELEASE_ERROR,
857*5c51f124SMoriah Waterland 				a_object, a_key);
858*5c51f124SMoriah Waterland 			perror(LOCK_FILENAME);
859*5c51f124SMoriah Waterland 			return (result);
860*5c51f124SMoriah Waterland 
861*5c51f124SMoriah Waterland 		/*
862*5c51f124SMoriah Waterland 		 * object is locked and specified key matches
863*5c51f124SMoriah Waterland 		 */
864*5c51f124SMoriah Waterland 		case FINDLOCK_FOUND:
865*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, MSG_LOCK_RELEASE_FOUND,
866*5c51f124SMoriah Waterland 				a_object, a_key);
867*5c51f124SMoriah Waterland 			(void) _decrementLockCount(a_fd, &theLock);
868*5c51f124SMoriah Waterland 			break;
869*5c51f124SMoriah Waterland 
870*5c51f124SMoriah Waterland 		/*
871*5c51f124SMoriah Waterland 		 * unknown return
872*5c51f124SMoriah Waterland 		 */
873*5c51f124SMoriah Waterland 		default:
874*5c51f124SMoriah Waterland 			result = FINDLOCK_ERROR;
875*5c51f124SMoriah Waterland 			break;
876*5c51f124SMoriah Waterland 
877*5c51f124SMoriah Waterland 	}
878*5c51f124SMoriah Waterland 	return (result);
879*5c51f124SMoriah Waterland }
880*5c51f124SMoriah Waterland 
881*5c51f124SMoriah Waterland /*
882*5c51f124SMoriah Waterland  * Name:	lock_status
883*5c51f124SMoriah Waterland  * Description:	implement lock status display/inquiry
884*5c51f124SMoriah Waterland  * Arguments:
885*5c51f124SMoriah Waterland  *	a_fd - file descriptor opened on the lock file
886*5c51f124SMoriah Waterland  *	a_key - key associated with lock to look up
887*5c51f124SMoriah Waterland  *	a_object - object associated with lock to look up
888*5c51f124SMoriah Waterland  *	a_quiet - quiet mode enabled flag
889*5c51f124SMoriah Waterland  * Returns: int
890*5c51f124SMoriah Waterland  *		== 0 - successful
891*5c51f124SMoriah Waterland  *		!= 0 - not successful
892*5c51f124SMoriah Waterland  */
893*5c51f124SMoriah Waterland 
894*5c51f124SMoriah Waterland static int
895*5c51f124SMoriah Waterland lock_status(int a_fd, char *a_key, char *a_object, int a_quiet)
896*5c51f124SMoriah Waterland {
897*5c51f124SMoriah Waterland 	ADMINLOCK_T	*pll;
898*5c51f124SMoriah Waterland 	LOCK_T		theLock;
899*5c51f124SMoriah Waterland 	RECORDNUM_T	recordNum = 0;
900*5c51f124SMoriah Waterland 	char		*pld;
901*5c51f124SMoriah Waterland 	int		found = 0;
902*5c51f124SMoriah Waterland 	long		pls;
903*5c51f124SMoriah Waterland 
904*5c51f124SMoriah Waterland 	/* entry debugging info */
905*5c51f124SMoriah Waterland 
906*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_STATUS_ENTRY,
907*5c51f124SMoriah Waterland 		a_key, a_object);
908*5c51f124SMoriah Waterland 
909*5c51f124SMoriah Waterland 	/* localize references to lock object */
910*5c51f124SMoriah Waterland 
911*5c51f124SMoriah Waterland 	pld = &theLock._lrLockData[0];
912*5c51f124SMoriah Waterland 	pll = &theLock._lrLock;
913*5c51f124SMoriah Waterland 	pls = sizeof (theLock._lrLockData);
914*5c51f124SMoriah Waterland 
915*5c51f124SMoriah Waterland 	bzero(pld, pls);
916*5c51f124SMoriah Waterland 
917*5c51f124SMoriah Waterland 	/* read and process each lock */
918*5c51f124SMoriah Waterland 
919*5c51f124SMoriah Waterland 	for (; pread(a_fd, pld, pls, pls*recordNum) == pls; recordNum++) {
920*5c51f124SMoriah Waterland 		/* debug info on this lock */
921*5c51f124SMoriah Waterland 
922*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LOCK_STATUS_READRECORD,
923*5c51f124SMoriah Waterland 			recordNum, pll->lockCount,
924*5c51f124SMoriah Waterland 			pll->lockObject, pll->lockKey, pll->lockPid,
925*5c51f124SMoriah Waterland 			pll->lockZoneId);
926*5c51f124SMoriah Waterland 
927*5c51f124SMoriah Waterland 		/* ignore if key specified and key does not match */
928*5c51f124SMoriah Waterland 
929*5c51f124SMoriah Waterland 		if ((*a_key != '\0') &&
930*5c51f124SMoriah Waterland 			(strcmp(pll->lockKey, a_key) != 0)) {
931*5c51f124SMoriah Waterland 			continue;
932*5c51f124SMoriah Waterland 		}
933*5c51f124SMoriah Waterland 
934*5c51f124SMoriah Waterland 		/* ignore if object specified and object does not match */
935*5c51f124SMoriah Waterland 
936*5c51f124SMoriah Waterland 		if ((*a_object != '\0') &&
937*5c51f124SMoriah Waterland 			(strcmp(pll->lockObject, a_object) != 0)) {
938*5c51f124SMoriah Waterland 			continue;
939*5c51f124SMoriah Waterland 		}
940*5c51f124SMoriah Waterland 
941*5c51f124SMoriah Waterland 		found++;
942*5c51f124SMoriah Waterland 
943*5c51f124SMoriah Waterland 		/* process next lock if quiet operation */
944*5c51f124SMoriah Waterland 
945*5c51f124SMoriah Waterland 		if (a_quiet != 0) {
946*5c51f124SMoriah Waterland 			continue;
947*5c51f124SMoriah Waterland 		}
948*5c51f124SMoriah Waterland 
949*5c51f124SMoriah Waterland 		/* output header if first lock object */
950*5c51f124SMoriah Waterland 
951*5c51f124SMoriah Waterland 		if (found == 1) {
952*5c51f124SMoriah Waterland 			(void) fprintf(stdout,
953*5c51f124SMoriah Waterland 				"%2s %2s %3s %8s %3s %9s %37s %s\n",
954*5c51f124SMoriah Waterland 				"i#", "l#", "cnt", "pid", "zid", "lock-type",
955*5c51f124SMoriah Waterland 				"---------------lock-key-------------",
956*5c51f124SMoriah Waterland 				"lock-object");
957*5c51f124SMoriah Waterland 		}
958*5c51f124SMoriah Waterland 
959*5c51f124SMoriah Waterland 		/* output status line for this lock object */
960*5c51f124SMoriah Waterland 
961*5c51f124SMoriah Waterland 		(void) fprintf(stdout,
962*5c51f124SMoriah Waterland 			"%2ld %2ld %3ld %8ld %3d %9s %37s %s\n",
963*5c51f124SMoriah Waterland 			recordNum, pll->lockRecordNum, pll->lockCount,
964*5c51f124SMoriah Waterland 			pll->lockPid, pll->lockZoneId,
965*5c51f124SMoriah Waterland 			pll->lockExclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR,
966*5c51f124SMoriah Waterland 			pll->lockKey,
967*5c51f124SMoriah Waterland 			*pll->lockObject == '\0' ? "*" : pll->lockObject);
968*5c51f124SMoriah Waterland 	}
969*5c51f124SMoriah Waterland 
970*5c51f124SMoriah Waterland 	/* return == 0 if found, != 0 if not found */
971*5c51f124SMoriah Waterland 
972*5c51f124SMoriah Waterland 	return (found == 0 ? 1 : 0);
973*5c51f124SMoriah Waterland }
974*5c51f124SMoriah Waterland 
975*5c51f124SMoriah Waterland /*
976*5c51f124SMoriah Waterland  * local utility functions
977*5c51f124SMoriah Waterland  */
978*5c51f124SMoriah Waterland 
979*5c51f124SMoriah Waterland /*
980*5c51f124SMoriah Waterland  * Name:	_lock_acquire
981*5c51f124SMoriah Waterland  * Description:	implement lock acquisition without wait/timeouts
982*5c51f124SMoriah Waterland  * Arguments:
983*5c51f124SMoriah Waterland  *	a_theLock - lock object filled with contents of existing lock
984*5c51f124SMoriah Waterland  *	a_fd - file descriptor opened on the lock file
985*5c51f124SMoriah Waterland  *	a_key - key associated with lock to acquire
986*5c51f124SMoriah Waterland  *	a_object - object associated with lock to acquire
987*5c51f124SMoriah Waterland  *	a_quiet - quiet mode enabled flag
988*5c51f124SMoriah Waterland  *	a_exclusive - exclusive/shared lock flag
989*5c51f124SMoriah Waterland  *	a_pid - if != 0 process i.d. to associate with this lock
990*5c51f124SMoriah Waterland  *	a_zid - if >= 0 zone i.d. to associate with this lock
991*5c51f124SMoriah Waterland  * Returns: FINDLOCK_T
992*5c51f124SMoriah Waterland  */
993*5c51f124SMoriah Waterland 
994*5c51f124SMoriah Waterland static FINDLOCK_T
995*5c51f124SMoriah Waterland _lock_acquire(LOCK_T *a_theLock, int a_fd, char *a_key,
996*5c51f124SMoriah Waterland 	char *a_object, int a_quiet, int a_exclusive, pid_t a_pid,
997*5c51f124SMoriah Waterland 	zoneid_t a_zid)
998*5c51f124SMoriah Waterland {
999*5c51f124SMoriah Waterland 	RECORDNUM_T	recordNum;
1000*5c51f124SMoriah Waterland 	FINDLOCK_T	result;
1001*5c51f124SMoriah Waterland 	char		key[LOCK_KEY_MAXLEN+1] = {'\0'};
1002*5c51f124SMoriah Waterland 
1003*5c51f124SMoriah Waterland 	/* entry debugging info */
1004*5c51f124SMoriah Waterland 
1005*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_ACQUIRE_ENTRY,
1006*5c51f124SMoriah Waterland 		a_key, a_object, a_quiet, a_exclusive);
1007*5c51f124SMoriah Waterland 
1008*5c51f124SMoriah Waterland 	/* is the specified object already locked? */
1009*5c51f124SMoriah Waterland 
1010*5c51f124SMoriah Waterland 	for (;;) {
1011*5c51f124SMoriah Waterland 		result = _findLock(a_theLock, &recordNum, a_fd, a_object,
1012*5c51f124SMoriah Waterland 			a_key);
1013*5c51f124SMoriah Waterland 
1014*5c51f124SMoriah Waterland 		if (result != FINDLOCK_LOCKED) {
1015*5c51f124SMoriah Waterland 			break;
1016*5c51f124SMoriah Waterland 		}
1017*5c51f124SMoriah Waterland 
1018*5c51f124SMoriah Waterland 		if (_validateLock(a_fd, a_theLock, a_quiet) == B_TRUE) {
1019*5c51f124SMoriah Waterland 			break;
1020*5c51f124SMoriah Waterland 		}
1021*5c51f124SMoriah Waterland 	}
1022*5c51f124SMoriah Waterland 
1023*5c51f124SMoriah Waterland 
1024*5c51f124SMoriah Waterland 	/* debug info on result of find of lock */
1025*5c51f124SMoriah Waterland 
1026*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_ACQUIRE_FINDRESULT,
1027*5c51f124SMoriah Waterland 		a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR,
1028*5c51f124SMoriah Waterland 		result, recordNum);
1029*5c51f124SMoriah Waterland 
1030*5c51f124SMoriah Waterland 	/* determine how to acquire the lock */
1031*5c51f124SMoriah Waterland 
1032*5c51f124SMoriah Waterland 	switch (result) {
1033*5c51f124SMoriah Waterland 		/*
1034*5c51f124SMoriah Waterland 		 * object is not locked but a key was specified
1035*5c51f124SMoriah Waterland 		 */
1036*5c51f124SMoriah Waterland 		case FINDLOCK_NOTLOCKED:
1037*5c51f124SMoriah Waterland 			log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR,
1038*5c51f124SMoriah Waterland 				MSG_LOCK_ACQUIRE_NOTLOCKED,
1039*5c51f124SMoriah Waterland 				a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR,
1040*5c51f124SMoriah Waterland 				a_object, a_key);
1041*5c51f124SMoriah Waterland 			break;
1042*5c51f124SMoriah Waterland 
1043*5c51f124SMoriah Waterland 		/*
1044*5c51f124SMoriah Waterland 		 * object is locked and no key was specified:
1045*5c51f124SMoriah Waterland 		 * - if lock is exclusively held, return "locked"
1046*5c51f124SMoriah Waterland 		 * - if exclusive lock requested, return "locked"
1047*5c51f124SMoriah Waterland 		 * - otherwise lock is shared and shared lock requested,
1048*5c51f124SMoriah Waterland 		 *   - increment lock count and return the key
1049*5c51f124SMoriah Waterland 		 */
1050*5c51f124SMoriah Waterland 		case FINDLOCK_LOCKED:
1051*5c51f124SMoriah Waterland 			/* return error if current lock exclusive */
1052*5c51f124SMoriah Waterland 
1053*5c51f124SMoriah Waterland 			if (a_theLock->_lrLock.lockExclusive) {
1054*5c51f124SMoriah Waterland 				break;
1055*5c51f124SMoriah Waterland 			}
1056*5c51f124SMoriah Waterland 
1057*5c51f124SMoriah Waterland 			/* return error if requesting exclusive lock */
1058*5c51f124SMoriah Waterland 
1059*5c51f124SMoriah Waterland 			if (a_exclusive) {
1060*5c51f124SMoriah Waterland 				break;
1061*5c51f124SMoriah Waterland 			}
1062*5c51f124SMoriah Waterland 
1063*5c51f124SMoriah Waterland 			/* shared requesting shared - add to shared lock */
1064*5c51f124SMoriah Waterland 
1065*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG,
1066*5c51f124SMoriah Waterland 				MSG_LOCK_ACQUIRE_LOCKED_SHARED,
1067*5c51f124SMoriah Waterland 				a_object, a_key);
1068*5c51f124SMoriah Waterland 
1069*5c51f124SMoriah Waterland 			/* increment shared lock count */
1070*5c51f124SMoriah Waterland 
1071*5c51f124SMoriah Waterland 			if (_incrementLockCount(a_fd, a_theLock) == 0) {
1072*5c51f124SMoriah Waterland 				result = FINDLOCK_LOCKACQUIRED;
1073*5c51f124SMoriah Waterland 			} else {
1074*5c51f124SMoriah Waterland 				result = FINDLOCK_ERROR;
1075*5c51f124SMoriah Waterland 			}
1076*5c51f124SMoriah Waterland 
1077*5c51f124SMoriah Waterland 			break;
1078*5c51f124SMoriah Waterland 
1079*5c51f124SMoriah Waterland 		/*
1080*5c51f124SMoriah Waterland 		 * object is not locked
1081*5c51f124SMoriah Waterland 		 */
1082*5c51f124SMoriah Waterland 		case FINDLOCK_NOTFOUND:
1083*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG,
1084*5c51f124SMoriah Waterland 				MSG_LOCK_ACQUIRE_NOTFOUND,
1085*5c51f124SMoriah Waterland 				a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR,
1086*5c51f124SMoriah Waterland 				a_object);
1087*5c51f124SMoriah Waterland 
1088*5c51f124SMoriah Waterland 			if (_addLock(key, a_fd, a_object, a_exclusive,
1089*5c51f124SMoriah Waterland 							a_pid, a_zid) == 0) {
1090*5c51f124SMoriah Waterland 				(void) strncpy(a_theLock->_lrLock.lockKey, key,
1091*5c51f124SMoriah Waterland 					sizeof (a_theLock->_lrLock.lockKey));
1092*5c51f124SMoriah Waterland 				result = FINDLOCK_LOCKACQUIRED;
1093*5c51f124SMoriah Waterland 			} else {
1094*5c51f124SMoriah Waterland 				result = FINDLOCK_ERROR;
1095*5c51f124SMoriah Waterland 			}
1096*5c51f124SMoriah Waterland 			break;
1097*5c51f124SMoriah Waterland 
1098*5c51f124SMoriah Waterland 		/*
1099*5c51f124SMoriah Waterland 		 * object is locked, key specified, specified key does not match
1100*5c51f124SMoriah Waterland 		 */
1101*5c51f124SMoriah Waterland 		case FINDLOCK_KEYMISMATCH:
1102*5c51f124SMoriah Waterland 			log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR,
1103*5c51f124SMoriah Waterland 				MSG_LOCK_ACQUIRE_KEYMISMATCH,
1104*5c51f124SMoriah Waterland 				a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR,
1105*5c51f124SMoriah Waterland 				a_object);
1106*5c51f124SMoriah Waterland 			break;
1107*5c51f124SMoriah Waterland 
1108*5c51f124SMoriah Waterland 		/*
1109*5c51f124SMoriah Waterland 		 * error determining if object is locked
1110*5c51f124SMoriah Waterland 		 */
1111*5c51f124SMoriah Waterland 		case FINDLOCK_ERROR:
1112*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_ERR, MSG_LOCK_ACQUIRE_ERROR,
1113*5c51f124SMoriah Waterland 				a_object, a_key, strerror(errno));
1114*5c51f124SMoriah Waterland 			break;
1115*5c51f124SMoriah Waterland 
1116*5c51f124SMoriah Waterland 		/*
1117*5c51f124SMoriah Waterland 		 * object is locked and specified key matches
1118*5c51f124SMoriah Waterland 		 */
1119*5c51f124SMoriah Waterland 		case FINDLOCK_FOUND:
1120*5c51f124SMoriah Waterland 			/* return locked if object currently locked */
1121*5c51f124SMoriah Waterland 			if (a_exclusive != a_theLock->_lrLock.lockExclusive) {
1122*5c51f124SMoriah Waterland 				result = FINDLOCK_LOCKED;
1123*5c51f124SMoriah Waterland 				break;
1124*5c51f124SMoriah Waterland 			}
1125*5c51f124SMoriah Waterland 
1126*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, MSG_LOCK_ACQUIRE_FOUND_INC,
1127*5c51f124SMoriah Waterland 				a_object, a_key,
1128*5c51f124SMoriah Waterland 				a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR);
1129*5c51f124SMoriah Waterland 
1130*5c51f124SMoriah Waterland 			/* increment shared lock */
1131*5c51f124SMoriah Waterland 
1132*5c51f124SMoriah Waterland 			if (_incrementLockCount(a_fd, a_theLock) == 0) {
1133*5c51f124SMoriah Waterland 				result = FINDLOCK_LOCKACQUIRED;
1134*5c51f124SMoriah Waterland 			} else {
1135*5c51f124SMoriah Waterland 				result = FINDLOCK_ERROR;
1136*5c51f124SMoriah Waterland 			}
1137*5c51f124SMoriah Waterland 			break;
1138*5c51f124SMoriah Waterland 
1139*5c51f124SMoriah Waterland 		/*
1140*5c51f124SMoriah Waterland 		 * unknown return
1141*5c51f124SMoriah Waterland 		 */
1142*5c51f124SMoriah Waterland 		default:
1143*5c51f124SMoriah Waterland 			result = FINDLOCK_ERROR;
1144*5c51f124SMoriah Waterland 			break;
1145*5c51f124SMoriah Waterland 	}
1146*5c51f124SMoriah Waterland 
1147*5c51f124SMoriah Waterland 	return (result);
1148*5c51f124SMoriah Waterland }
1149*5c51f124SMoriah Waterland 
1150*5c51f124SMoriah Waterland /*
1151*5c51f124SMoriah Waterland  * Name:	_openLockFile
1152*5c51f124SMoriah Waterland  * Description:	open the lock file, acquiring exclusive record locks
1153*5c51f124SMoriah Waterland  * Arguments:
1154*5c51f124SMoriah Waterland  *	a_root - root of file system to manipulate locks on
1155*5c51f124SMoriah Waterland  * Returns: int
1156*5c51f124SMoriah Waterland  *		>= 0 - successful - file descriptor lock file opened on
1157*5c51f124SMoriah Waterland  *		< 0 - not successful
1158*5c51f124SMoriah Waterland  */
1159*5c51f124SMoriah Waterland 
1160*5c51f124SMoriah Waterland static int
1161*5c51f124SMoriah Waterland _openLockFile(char *a_root)
1162*5c51f124SMoriah Waterland {
1163*5c51f124SMoriah Waterland 	WAITER_T	waiter;
1164*5c51f124SMoriah Waterland 	char		lockpath[MAXPATHLEN];
1165*5c51f124SMoriah Waterland 	int		fd;
1166*5c51f124SMoriah Waterland 	int		result;
1167*5c51f124SMoriah Waterland 
1168*5c51f124SMoriah Waterland 	/* entry debugging info */
1169*5c51f124SMoriah Waterland 
1170*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_OPENFILE_ENTRY,
1171*5c51f124SMoriah Waterland 		a_root, LOCK_FILENAME);
1172*5c51f124SMoriah Waterland 
1173*5c51f124SMoriah Waterland 	/* generate path to lock directory */
1174*5c51f124SMoriah Waterland 
1175*5c51f124SMoriah Waterland 	(void) snprintf(lockpath, sizeof (lockpath), "%s/%s",
1176*5c51f124SMoriah Waterland 		a_root, LOCK_DIRECTORY);
1177*5c51f124SMoriah Waterland 
1178*5c51f124SMoriah Waterland 	if (access(lockpath, F_OK) != 0) {
1179*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_ROOTDIR_INVALID,
1180*5c51f124SMoriah Waterland 			lockpath, strerror(errno));
1181*5c51f124SMoriah Waterland 		return (-1);
1182*5c51f124SMoriah Waterland 	}
1183*5c51f124SMoriah Waterland 
1184*5c51f124SMoriah Waterland 	/* generate path to lock file */
1185*5c51f124SMoriah Waterland 
1186*5c51f124SMoriah Waterland 	(void) snprintf(lockpath, sizeof (lockpath),
1187*5c51f124SMoriah Waterland 		"%s/%s", a_root, LOCK_FILENAME);
1188*5c51f124SMoriah Waterland 
1189*5c51f124SMoriah Waterland 	/* wait for open to succeed up to limits */
1190*5c51f124SMoriah Waterland 
1191*5c51f124SMoriah Waterland 	for (waiter = WAITER_INITIAL;
1192*5c51f124SMoriah Waterland 		waiter < WAITER_MAX;
1193*5c51f124SMoriah Waterland 		waiter = WAITER_NEXT(waiter)) {
1194*5c51f124SMoriah Waterland 
1195*5c51f124SMoriah Waterland 		/* LINTED O_CREAT without O_EXCL specified in call to open() */
1196*5c51f124SMoriah Waterland 		fd = open(lockpath, O_CREAT|O_RDWR, LOCK_FILEMODE);
1197*5c51f124SMoriah Waterland 
1198*5c51f124SMoriah Waterland 		/* break out of loop if file opened */
1199*5c51f124SMoriah Waterland 
1200*5c51f124SMoriah Waterland 		if (fd >= 0) {
1201*5c51f124SMoriah Waterland 			break;
1202*5c51f124SMoriah Waterland 		}
1203*5c51f124SMoriah Waterland 
1204*5c51f124SMoriah Waterland 		/* failed - exit loop if due to access (permissions) failure */
1205*5c51f124SMoriah Waterland 
1206*5c51f124SMoriah Waterland 		if (errno == EACCES) {
1207*5c51f124SMoriah Waterland 			break;
1208*5c51f124SMoriah Waterland 		}
1209*5c51f124SMoriah Waterland 
1210*5c51f124SMoriah Waterland 		/* file is busy - wait and try again */
1211*5c51f124SMoriah Waterland 
1212*5c51f124SMoriah Waterland 		if (waiter == WAITER_INITIAL) {
1213*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG,
1214*5c51f124SMoriah Waterland 				MSG_LOCK_OPENFILE_SLEEPING,
1215*5c51f124SMoriah Waterland 				strerror(errno), waiter);
1216*5c51f124SMoriah Waterland 		}
1217*5c51f124SMoriah Waterland 
1218*5c51f124SMoriah Waterland 		(void) sleep(waiter);
1219*5c51f124SMoriah Waterland 	}
1220*5c51f124SMoriah Waterland 
1221*5c51f124SMoriah Waterland 	/* if open filed generate error message and return error */
1222*5c51f124SMoriah Waterland 
1223*5c51f124SMoriah Waterland 	if (fd < 0) {
1224*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LOCK_OPENFILE_FAILURE,
1225*5c51f124SMoriah Waterland 			strerror(errno));
1226*5c51f124SMoriah Waterland 		perror(lockpath);
1227*5c51f124SMoriah Waterland 		return (-1);
1228*5c51f124SMoriah Waterland 	}
1229*5c51f124SMoriah Waterland 
1230*5c51f124SMoriah Waterland 	/*
1231*5c51f124SMoriah Waterland 	 * lock file opened - acquire exclusive section lock on entire file;
1232*5c51f124SMoriah Waterland 	 * wait for lockf to succeed up to limits
1233*5c51f124SMoriah Waterland 	 */
1234*5c51f124SMoriah Waterland 
1235*5c51f124SMoriah Waterland 	for (waiter = WAITER_INITIAL;
1236*5c51f124SMoriah Waterland 		waiter < WAITER_MAX;
1237*5c51f124SMoriah Waterland 		waiter = WAITER_NEXT(waiter)) {
1238*5c51f124SMoriah Waterland 
1239*5c51f124SMoriah Waterland 		/* acquire exclusive section lock on entire file */
1240*5c51f124SMoriah Waterland 
1241*5c51f124SMoriah Waterland 		result = lockf(fd, F_LOCK, 0xFFFFF);
1242*5c51f124SMoriah Waterland 
1243*5c51f124SMoriah Waterland 		/* break out of loop if entire file locked */
1244*5c51f124SMoriah Waterland 
1245*5c51f124SMoriah Waterland 		if (result == 0) {
1246*5c51f124SMoriah Waterland 			break;
1247*5c51f124SMoriah Waterland 		}
1248*5c51f124SMoriah Waterland 
1249*5c51f124SMoriah Waterland 		/* file is busy - wait and try again */
1250*5c51f124SMoriah Waterland 
1251*5c51f124SMoriah Waterland 		if (waiter == WAITER_INITIAL) {
1252*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, MSG_LOCK_OPENFILE_SLEEP2,
1253*5c51f124SMoriah Waterland 				strerror(errno), waiter);
1254*5c51f124SMoriah Waterland 		}
1255*5c51f124SMoriah Waterland 
1256*5c51f124SMoriah Waterland 		(void) sleep(waiter);
1257*5c51f124SMoriah Waterland 	}
1258*5c51f124SMoriah Waterland 
1259*5c51f124SMoriah Waterland 	/* if section lock failed generate error message and return error */
1260*5c51f124SMoriah Waterland 
1261*5c51f124SMoriah Waterland 	if (result < 0) {
1262*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LOCK_OPENFILE_FAIL2,
1263*5c51f124SMoriah Waterland 			strerror(errno));
1264*5c51f124SMoriah Waterland 		perror(lockpath);
1265*5c51f124SMoriah Waterland 		(void) close(fd);
1266*5c51f124SMoriah Waterland 		return (-1);
1267*5c51f124SMoriah Waterland 	}
1268*5c51f124SMoriah Waterland 
1269*5c51f124SMoriah Waterland 	/* file opened and locked - return success */
1270*5c51f124SMoriah Waterland 
1271*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_OPENFILE_SUCCESS, fd);
1272*5c51f124SMoriah Waterland 
1273*5c51f124SMoriah Waterland 	return (fd);
1274*5c51f124SMoriah Waterland }
1275*5c51f124SMoriah Waterland 
1276*5c51f124SMoriah Waterland /*
1277*5c51f124SMoriah Waterland  * Name:	_lockMatch
1278*5c51f124SMoriah Waterland  * Description:	Compare two lock objects using file name match criteria
1279*5c51f124SMoriah Waterland  * Arguments:
1280*5c51f124SMoriah Waterland  *	a_s1Lock - first lock object to compare against the second
1281*5c51f124SMoriah Waterland  *	a_s2Lock - second lock object to compare against the first
1282*5c51f124SMoriah Waterland  * Returns:
1283*5c51f124SMoriah Waterland  * 	== 0 - the locks match at some level
1284*5c51f124SMoriah Waterland  *	!= 0 - the locks do not match at any level
1285*5c51f124SMoriah Waterland  */
1286*5c51f124SMoriah Waterland 
1287*5c51f124SMoriah Waterland static int
1288*5c51f124SMoriah Waterland _lockMatch(char *a_s1Lock, char *a_s2Lock)
1289*5c51f124SMoriah Waterland {
1290*5c51f124SMoriah Waterland 	boolean_t	s1Sfx = B_FALSE;
1291*5c51f124SMoriah Waterland 	boolean_t	s2Sfx = B_FALSE;
1292*5c51f124SMoriah Waterland 	char		*final1Lock = (char *)NULL;
1293*5c51f124SMoriah Waterland 	char		*final2Lock = (char *)NULL;
1294*5c51f124SMoriah Waterland 	char		s1Buf[MAXPATHLEN] = {'\0'};
1295*5c51f124SMoriah Waterland 	char		s1Prefix[MAXPATHLEN] = {'\0'};
1296*5c51f124SMoriah Waterland 	char		s2Buf[MAXPATHLEN] = {'\0'};
1297*5c51f124SMoriah Waterland 	char		s2Prefix[MAXPATHLEN] = {'\0'};
1298*5c51f124SMoriah Waterland 	int		result = 0;
1299*5c51f124SMoriah Waterland 	int		s1Cnt;
1300*5c51f124SMoriah Waterland 	int		s2Cnt;
1301*5c51f124SMoriah Waterland 
1302*5c51f124SMoriah Waterland 	/* entry assertions */
1303*5c51f124SMoriah Waterland 
1304*5c51f124SMoriah Waterland 	assert(a_s1Lock != (char *)NULL);
1305*5c51f124SMoriah Waterland 	assert(a_s2Lock != (char *)NULL);
1306*5c51f124SMoriah Waterland 
1307*5c51f124SMoriah Waterland 	/* entry debugging info */
1308*5c51f124SMoriah Waterland 
1309*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_ENTRY, a_s1Lock, a_s2Lock);
1310*5c51f124SMoriah Waterland 
1311*5c51f124SMoriah Waterland 	/*
1312*5c51f124SMoriah Waterland 	 * attempt to find a common anchor between the two locks; that is,
1313*5c51f124SMoriah Waterland 	 * find the first node in the first lock that matches any node
1314*5c51f124SMoriah Waterland 	 * in the second lock; for example:
1315*5c51f124SMoriah Waterland 	 * --> a/b/c vs b/c/d
1316*5c51f124SMoriah Waterland 	 * -> common anchor is "b"; comparison would expand to:
1317*5c51f124SMoriah Waterland 	 * --> a/b/c/? vs ?/b/c/d
1318*5c51f124SMoriah Waterland 	 */
1319*5c51f124SMoriah Waterland 
1320*5c51f124SMoriah Waterland 	/* process each node in the first lock */
1321*5c51f124SMoriah Waterland 
1322*5c51f124SMoriah Waterland 	for (s1Cnt = 0; ; s1Cnt++) {
1323*5c51f124SMoriah Waterland 		/* get next first lock node */
1324*5c51f124SMoriah Waterland 
1325*5c51f124SMoriah Waterland 		pkgstrGetToken_r((char *)NULL, a_s1Lock, s1Cnt, "/",
1326*5c51f124SMoriah Waterland 			s1Buf, sizeof (s1Buf));
1327*5c51f124SMoriah Waterland 
1328*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_FSTNODE, s1Cnt, s1Buf);
1329*5c51f124SMoriah Waterland 
1330*5c51f124SMoriah Waterland 		/* exit if no more nodes left */
1331*5c51f124SMoriah Waterland 
1332*5c51f124SMoriah Waterland 		if (s1Buf[0] == '\0') {
1333*5c51f124SMoriah Waterland 			break;
1334*5c51f124SMoriah Waterland 		}
1335*5c51f124SMoriah Waterland 
1336*5c51f124SMoriah Waterland 		/* discover "." prefix for this node */
1337*5c51f124SMoriah Waterland 
1338*5c51f124SMoriah Waterland 		pkgstrGetToken_r((char *)NULL, s1Buf, 0, ".", s1Prefix,
1339*5c51f124SMoriah Waterland 			sizeof (s1Prefix));
1340*5c51f124SMoriah Waterland 
1341*5c51f124SMoriah Waterland 		s1Sfx = (strlen(s1Prefix) == strlen(s1Buf) ? B_FALSE : B_TRUE);
1342*5c51f124SMoriah Waterland 
1343*5c51f124SMoriah Waterland 		/* search each second lock node; look for the first node lock */
1344*5c51f124SMoriah Waterland 
1345*5c51f124SMoriah Waterland 		for (s2Cnt = 0; ; s2Cnt++) {
1346*5c51f124SMoriah Waterland 			/* get next second lock node */
1347*5c51f124SMoriah Waterland 
1348*5c51f124SMoriah Waterland 			pkgstrGetToken_r((char *)NULL, a_s2Lock, s2Cnt, "/",
1349*5c51f124SMoriah Waterland 				s2Buf, sizeof (s2Buf));
1350*5c51f124SMoriah Waterland 
1351*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_SCNDNODE, s2Cnt,
1352*5c51f124SMoriah Waterland 				s2Buf);
1353*5c51f124SMoriah Waterland 
1354*5c51f124SMoriah Waterland 			/* exit if no nodes left */
1355*5c51f124SMoriah Waterland 
1356*5c51f124SMoriah Waterland 			if (s2Buf[0] == '\0') {
1357*5c51f124SMoriah Waterland 				break;
1358*5c51f124SMoriah Waterland 			}
1359*5c51f124SMoriah Waterland 
1360*5c51f124SMoriah Waterland 			/* discover "." prefix for this node */
1361*5c51f124SMoriah Waterland 
1362*5c51f124SMoriah Waterland 			pkgstrGetToken_r((char *)NULL, s2Buf, 0, ".", s2Prefix,
1363*5c51f124SMoriah Waterland 				sizeof (s2Prefix));
1364*5c51f124SMoriah Waterland 
1365*5c51f124SMoriah Waterland 			s2Sfx = (strlen(s2Prefix) ==
1366*5c51f124SMoriah Waterland 					strlen(s2Buf) ? B_FALSE : B_TRUE);
1367*5c51f124SMoriah Waterland 
1368*5c51f124SMoriah Waterland 			/*
1369*5c51f124SMoriah Waterland 			 * process this pair of nodes:
1370*5c51f124SMoriah Waterland 			 * if both nodes do not have a prefix, then directly
1371*5c51f124SMoriah Waterland 			 * compare the nodes (e.g. a/b vs c/d: a vs c, b vs d)
1372*5c51f124SMoriah Waterland 			 * and break out of the loop if there is a match;
1373*5c51f124SMoriah Waterland 			 * otherwise, compare prefixes and break out of the
1374*5c51f124SMoriah Waterland 			 * loop if there is a match (e.g. a.* / b.* vs
1375*5c51f124SMoriah Waterland 			 * vs c.* / d.*: a.* vs c.*, a.* vs d.*, b.* vs c.*,
1376*5c51f124SMoriah Waterland 			 * b.* vs d.*).
1377*5c51f124SMoriah Waterland 			 */
1378*5c51f124SMoriah Waterland 
1379*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_NODES, s1Buf,
1380*5c51f124SMoriah Waterland 				s1Prefix, s1Sfx, s2Buf, s2Prefix, s2Sfx);
1381*5c51f124SMoriah Waterland 
1382*5c51f124SMoriah Waterland 			if ((s1Sfx == B_FALSE) || (s2Sfx == B_FALSE)) {
1383*5c51f124SMoriah Waterland 				/* one doesnt have a prefix direct comparison */
1384*5c51f124SMoriah Waterland 
1385*5c51f124SMoriah Waterland 				if (strcmp(s1Buf, s2Buf) == 0) {
1386*5c51f124SMoriah Waterland 					log_msg(LOG_MSG_DEBUG,
1387*5c51f124SMoriah Waterland 						MSG_LCKMCH_DIRMCH,
1388*5c51f124SMoriah Waterland 						s1Buf, s2Buf);
1389*5c51f124SMoriah Waterland 					break;
1390*5c51f124SMoriah Waterland 				}
1391*5c51f124SMoriah Waterland 
1392*5c51f124SMoriah Waterland 				/* nodes do not directly match, continue */
1393*5c51f124SMoriah Waterland 
1394*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_DIRNOMCH,
1395*5c51f124SMoriah Waterland 						s1Buf, s2Buf);
1396*5c51f124SMoriah Waterland 				continue;
1397*5c51f124SMoriah Waterland 			}
1398*5c51f124SMoriah Waterland 
1399*5c51f124SMoriah Waterland 			/* both have prefix, compare prefixes */
1400*5c51f124SMoriah Waterland 
1401*5c51f124SMoriah Waterland 			if (strcmp(s1Prefix, s2Prefix) == 0) {
1402*5c51f124SMoriah Waterland 				log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_PFXMCH,
1403*5c51f124SMoriah Waterland 					s1Prefix, s2Prefix);
1404*5c51f124SMoriah Waterland 				break;
1405*5c51f124SMoriah Waterland 			}
1406*5c51f124SMoriah Waterland 
1407*5c51f124SMoriah Waterland 			/* prefixes do not match, continue */
1408*5c51f124SMoriah Waterland 
1409*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_PFXNOMCH, s1Prefix,
1410*5c51f124SMoriah Waterland 				s2Prefix);
1411*5c51f124SMoriah Waterland 		}
1412*5c51f124SMoriah Waterland 
1413*5c51f124SMoriah Waterland 		/*
1414*5c51f124SMoriah Waterland 		 * match found if not at the end of the second lock node list,
1415*5c51f124SMoriah Waterland 		 * break out of loop because some match between the two lock
1416*5c51f124SMoriah Waterland 		 * objects has been found
1417*5c51f124SMoriah Waterland 		 */
1418*5c51f124SMoriah Waterland 
1419*5c51f124SMoriah Waterland 		if (s2Buf[0] != '\0') {
1420*5c51f124SMoriah Waterland 			break;
1421*5c51f124SMoriah Waterland 		}
1422*5c51f124SMoriah Waterland 	}
1423*5c51f124SMoriah Waterland 
1424*5c51f124SMoriah Waterland 	/*
1425*5c51f124SMoriah Waterland 	 * at this point, either a match has been found between the nodes in
1426*5c51f124SMoriah Waterland 	 * the two lock objects, or there is no commonality at all between
1427*5c51f124SMoriah Waterland 	 * the two lock objects.
1428*5c51f124SMoriah Waterland 	 *
1429*5c51f124SMoriah Waterland 	 * s1Buf[0] == '\0' && s2Buf[0] == '\0':
1430*5c51f124SMoriah Waterland 	 * --> nothing in first lock matches anything in second lock:
1431*5c51f124SMoriah Waterland 	 * ----> (s1Cnt == 1) || (s2Cnt == 1) && (s1Sfx == B_FALSE)
1432*5c51f124SMoriah Waterland 	 * ----> || (s2Sfx == B_FALSE)
1433*5c51f124SMoriah Waterland 	 * --------> an absolute lock do not match
1434*5c51f124SMoriah Waterland 	 * ----> else both object locks have nothing in common - match
1435*5c51f124SMoriah Waterland 	 *
1436*5c51f124SMoriah Waterland 	 * s2Buf[0] != '\0' && s1Buf[0] != '\0' && s1Cnt > 0 && s2Cnt > 0
1437*5c51f124SMoriah Waterland 	 * --> locks have incompatible overlaps - no match, such as:
1438*5c51f124SMoriah Waterland 	 * ---->  a.* / b.* / c.* / d.*   and   y.* / b.* / c.*
1439*5c51f124SMoriah Waterland 	 *
1440*5c51f124SMoriah Waterland 	 * s1Cnt == 0 && s2Cnt == 0:
1441*5c51f124SMoriah Waterland 	 * --> locks begin with same node - do comparison
1442*5c51f124SMoriah Waterland 	 *
1443*5c51f124SMoriah Waterland 	 * s1Cnt != 0 && s2Cnt == 0 && s2Buf[0] != '\0'
1444*5c51f124SMoriah Waterland 	 * --> second lock is subset of first lock
1445*5c51f124SMoriah Waterland 	 *
1446*5c51f124SMoriah Waterland 	 * s2Cnt == 0 && s2Buf[0] != '\0':
1447*5c51f124SMoriah Waterland 	 * --> s1Buf[s1Cnt] matches s2Buf[0] - second is subset of first
1448*5c51f124SMoriah Waterland 	 *
1449*5c51f124SMoriah Waterland 	 * s2Cnt != 0 && s1Cnt == 0 && s1Buf[0] != '\0':
1450*5c51f124SMoriah Waterland 	 * --> first lock is subset of second lock
1451*5c51f124SMoriah Waterland 	 *
1452*5c51f124SMoriah Waterland 	 */
1453*5c51f124SMoriah Waterland 
1454*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_FSTLCK, s1Cnt, s1Buf,
1455*5c51f124SMoriah Waterland 		s1Prefix, s1Sfx);
1456*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_SCNDLCK, s2Cnt, s2Buf,
1457*5c51f124SMoriah Waterland 		s2Prefix, s2Sfx);
1458*5c51f124SMoriah Waterland 
1459*5c51f124SMoriah Waterland 	/* process any direct comparisons that might be possible */
1460*5c51f124SMoriah Waterland 
1461*5c51f124SMoriah Waterland 	if ((s1Buf[0] == '\0') && (s2Buf[0] == '\0')) {
1462*5c51f124SMoriah Waterland 		/* nothing in first matches anything in second lock */
1463*5c51f124SMoriah Waterland 
1464*5c51f124SMoriah Waterland 		if (((s1Cnt == 1) || (s2Cnt == 1)) &&
1465*5c51f124SMoriah Waterland 			((s1Sfx == B_FALSE) || (s2Sfx == B_FALSE))) {
1466*5c51f124SMoriah Waterland 			/* two absolute locks match (e.g. 'file' and 'dir') */
1467*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_ABSNOMCH, a_s1Lock,
1468*5c51f124SMoriah Waterland 				a_s2Lock);
1469*5c51f124SMoriah Waterland 			return (1);
1470*5c51f124SMoriah Waterland 		}
1471*5c51f124SMoriah Waterland 
1472*5c51f124SMoriah Waterland 		/* two object locks have nothing in common: match */
1473*5c51f124SMoriah Waterland 
1474*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_OBJMCH, a_s1Lock, a_s2Lock);
1475*5c51f124SMoriah Waterland 
1476*5c51f124SMoriah Waterland 		return (0);
1477*5c51f124SMoriah Waterland 	}
1478*5c51f124SMoriah Waterland 
1479*5c51f124SMoriah Waterland 	if ((s2Buf[0] != '\0') && (s1Buf[0] != '\0') &&
1480*5c51f124SMoriah Waterland 						(s1Cnt > 0) && (s2Cnt > 0)) {
1481*5c51f124SMoriah Waterland 		/* incompatible overlapping objects */
1482*5c51f124SMoriah Waterland 
1483*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_OVLPNOMCH, a_s1Lock, a_s2Lock,
1484*5c51f124SMoriah Waterland 			s1Cnt+1, s1Buf);
1485*5c51f124SMoriah Waterland 
1486*5c51f124SMoriah Waterland 		return (1);
1487*5c51f124SMoriah Waterland 	}
1488*5c51f124SMoriah Waterland 
1489*5c51f124SMoriah Waterland 	/*
1490*5c51f124SMoriah Waterland 	 * must compare each node of each lock to determine match;
1491*5c51f124SMoriah Waterland 	 * start off at the first byte of both locks
1492*5c51f124SMoriah Waterland 	 */
1493*5c51f124SMoriah Waterland 
1494*5c51f124SMoriah Waterland 	final1Lock = a_s1Lock;
1495*5c51f124SMoriah Waterland 	final2Lock = a_s2Lock;
1496*5c51f124SMoriah Waterland 
1497*5c51f124SMoriah Waterland 	if ((s1Cnt == 0) && (s2Cnt == 0)) {
1498*5c51f124SMoriah Waterland 		/* both have first match - start comparison from the begining */
1499*5c51f124SMoriah Waterland 
1500*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_SAME, a_s1Lock, a_s2Lock,
1501*5c51f124SMoriah Waterland 			s1Buf);
1502*5c51f124SMoriah Waterland 
1503*5c51f124SMoriah Waterland 	} else if ((s1Cnt != 0) && (s2Cnt == 0) && (s2Buf[0] != '\0')) {
1504*5c51f124SMoriah Waterland 		/* second lock begins somewhere inside of the first lock */
1505*5c51f124SMoriah Waterland 
1506*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_SCNDSUB, a_s2Lock, a_s1Lock,
1507*5c51f124SMoriah Waterland 			s1Cnt+1, s1Buf);
1508*5c51f124SMoriah Waterland 
1509*5c51f124SMoriah Waterland 		/* advance first lock to matching node in second lock */
1510*5c51f124SMoriah Waterland 
1511*5c51f124SMoriah Waterland 		if (strchr(a_s1Lock, '/') != (char *)NULL) {
1512*5c51f124SMoriah Waterland 			for (; s1Cnt > 0 && (*final1Lock != '\0');
1513*5c51f124SMoriah Waterland 				final1Lock++) {
1514*5c51f124SMoriah Waterland 				if (*final1Lock == '/') {
1515*5c51f124SMoriah Waterland 					s1Cnt--;
1516*5c51f124SMoriah Waterland 				}
1517*5c51f124SMoriah Waterland 			}
1518*5c51f124SMoriah Waterland 		}
1519*5c51f124SMoriah Waterland 	} else if ((s2Cnt != 0) && (s1Cnt == 0) && (s1Buf[0] != '\0')) {
1520*5c51f124SMoriah Waterland 		/* first lock begins somewhere inside of the second lock */
1521*5c51f124SMoriah Waterland 
1522*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_FRSTSUB, a_s1Lock, a_s2Lock,
1523*5c51f124SMoriah Waterland 			s2Cnt+1, s2Buf);
1524*5c51f124SMoriah Waterland 
1525*5c51f124SMoriah Waterland 		/* advance second lock to matching node in first lock */
1526*5c51f124SMoriah Waterland 
1527*5c51f124SMoriah Waterland 		if (strchr(a_s2Lock, '/') != (char *)NULL) {
1528*5c51f124SMoriah Waterland 			for (; s2Cnt > 0 && (*final2Lock != '\0');
1529*5c51f124SMoriah Waterland 				final2Lock++) {
1530*5c51f124SMoriah Waterland 				if (*final2Lock == '/') {
1531*5c51f124SMoriah Waterland 					s2Cnt--;
1532*5c51f124SMoriah Waterland 				}
1533*5c51f124SMoriah Waterland 			}
1534*5c51f124SMoriah Waterland 		}
1535*5c51f124SMoriah Waterland 	} else {
1536*5c51f124SMoriah Waterland 		/* unknown condition (probably impossible): directly compare */
1537*5c51f124SMoriah Waterland 
1538*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LCKMCH_DONTKNOW, a_s1Lock, a_s2Lock);
1539*5c51f124SMoriah Waterland 	}
1540*5c51f124SMoriah Waterland 
1541*5c51f124SMoriah Waterland 	/*
1542*5c51f124SMoriah Waterland 	 * locks have common node - compare from that node forward
1543*5c51f124SMoriah Waterland 	 */
1544*5c51f124SMoriah Waterland 
1545*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_READY, final1Lock, final2Lock);
1546*5c51f124SMoriah Waterland 
1547*5c51f124SMoriah Waterland 	/* compare each node (prefix) - success when no more nodes to compare */
1548*5c51f124SMoriah Waterland 
1549*5c51f124SMoriah Waterland 	for (s1Cnt = 0; ; s1Cnt++) {
1550*5c51f124SMoriah Waterland 		/* get next node from first lock */
1551*5c51f124SMoriah Waterland 
1552*5c51f124SMoriah Waterland 		pkgstrGetToken_r((char *)NULL, final1Lock, s1Cnt, "/", s1Buf,
1553*5c51f124SMoriah Waterland 			sizeof (s1Buf));
1554*5c51f124SMoriah Waterland 
1555*5c51f124SMoriah Waterland 		/* success if at end of lock */
1556*5c51f124SMoriah Waterland 
1557*5c51f124SMoriah Waterland 		if (s1Buf[0] == '\0') {
1558*5c51f124SMoriah Waterland 			break;
1559*5c51f124SMoriah Waterland 		}
1560*5c51f124SMoriah Waterland 
1561*5c51f124SMoriah Waterland 		/* get next node from second lock */
1562*5c51f124SMoriah Waterland 
1563*5c51f124SMoriah Waterland 		pkgstrGetToken_r((char *)NULL, final2Lock, s1Cnt, "/", s2Buf,
1564*5c51f124SMoriah Waterland 			sizeof (s2Buf));
1565*5c51f124SMoriah Waterland 
1566*5c51f124SMoriah Waterland 		/* success if at end of lock */
1567*5c51f124SMoriah Waterland 
1568*5c51f124SMoriah Waterland 		if (s2Buf[0] == '\0') {
1569*5c51f124SMoriah Waterland 			break;
1570*5c51f124SMoriah Waterland 		}
1571*5c51f124SMoriah Waterland 
1572*5c51f124SMoriah Waterland 		/* compare both nodes */
1573*5c51f124SMoriah Waterland 
1574*5c51f124SMoriah Waterland 		result = fnmatch(s1Buf, s2Buf, 0);
1575*5c51f124SMoriah Waterland 		if (result != 0) {
1576*5c51f124SMoriah Waterland 			result = fnmatch(s2Buf, s1Buf, 0);
1577*5c51f124SMoriah Waterland 		}
1578*5c51f124SMoriah Waterland 
1579*5c51f124SMoriah Waterland 		/* failure if nodes do not match */
1580*5c51f124SMoriah Waterland 
1581*5c51f124SMoriah Waterland 		if (result != 0) {
1582*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_NODEFAIL,
1583*5c51f124SMoriah Waterland 				s1Cnt, s1Buf, s2Buf);
1584*5c51f124SMoriah Waterland 			return (1);
1585*5c51f124SMoriah Waterland 		}
1586*5c51f124SMoriah Waterland 
1587*5c51f124SMoriah Waterland 		/* nodes match, continue and compare next set of nodes */
1588*5c51f124SMoriah Waterland 
1589*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_NODEOK, s1Cnt, s1Buf, s2Buf);
1590*5c51f124SMoriah Waterland 	}
1591*5c51f124SMoriah Waterland 
1592*5c51f124SMoriah Waterland 	/* no more nodes to compare - locks match */
1593*5c51f124SMoriah Waterland 
1594*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_MATCHOK, final1Lock, final2Lock);
1595*5c51f124SMoriah Waterland 
1596*5c51f124SMoriah Waterland 	return (0);
1597*5c51f124SMoriah Waterland }
1598*5c51f124SMoriah Waterland 
1599*5c51f124SMoriah Waterland /*
1600*5c51f124SMoriah Waterland  * Name:	_findLock
1601*5c51f124SMoriah Waterland  * Description:	Locate specified lock in lock file
1602*5c51f124SMoriah Waterland  * Arguments:
1603*5c51f124SMoriah Waterland  *	a_theLock - lock object filled with contents of lock (if found)
1604*5c51f124SMoriah Waterland  *	r_recordNum - will contain record number if lock found
1605*5c51f124SMoriah Waterland  *		- will be RECORDNUM_NONE if lock not found
1606*5c51f124SMoriah Waterland  *	a_fd - file descriptor opened on the lock file
1607*5c51f124SMoriah Waterland  *	a_key - key associated with lock to look up
1608*5c51f124SMoriah Waterland  *	a_object - object associated with lock to look up
1609*5c51f124SMoriah Waterland  * Returns:
1610*5c51f124SMoriah Waterland  *	FINDLOCK_FOUND - specified lock found; a_theLock contains contents
1611*5c51f124SMoriah Waterland  *		of found lock, r_recordNum contain record number of lock
1612*5c51f124SMoriah Waterland  *	FINDLOCK_ERROR - failed - error occurred looking up the lock
1613*5c51f124SMoriah Waterland  *	FINDLOCK_NOTFOUND - specified object is not locked
1614*5c51f124SMoriah Waterland  *	FINDLOCK_KEYMISMATCH - object lock found but specified key doesnt match
1615*5c51f124SMoriah Waterland  *	FINDLOCK_LOCKED - object lock found but no key specified
1616*5c51f124SMoriah Waterland  *	FINDLOCK_NOTLOCKED - object not locked
1617*5c51f124SMoriah Waterland  */
1618*5c51f124SMoriah Waterland 
1619*5c51f124SMoriah Waterland static FINDLOCK_T
1620*5c51f124SMoriah Waterland _findLock(LOCK_T *a_theLock, RECORDNUM_T *r_recordNum,
1621*5c51f124SMoriah Waterland 	int a_fd, char *a_object, char *a_key)
1622*5c51f124SMoriah Waterland {
1623*5c51f124SMoriah Waterland 	ADMINLOCK_T	*pll;
1624*5c51f124SMoriah Waterland 	char		*pld;
1625*5c51f124SMoriah Waterland 	int		recordNum = 0;
1626*5c51f124SMoriah Waterland 	long		pls;
1627*5c51f124SMoriah Waterland 	off_t		pos;
1628*5c51f124SMoriah Waterland 
1629*5c51f124SMoriah Waterland 	/* reset returned record number to "none" */
1630*5c51f124SMoriah Waterland 
1631*5c51f124SMoriah Waterland 	*r_recordNum = RECORDNUM_NONE;
1632*5c51f124SMoriah Waterland 
1633*5c51f124SMoriah Waterland 	/* localize references to lock object */
1634*5c51f124SMoriah Waterland 
1635*5c51f124SMoriah Waterland 	pld = &a_theLock->_lrLockData[0];
1636*5c51f124SMoriah Waterland 	pll = &a_theLock->_lrLock;
1637*5c51f124SMoriah Waterland 	pls = sizeof (a_theLock->_lrLockData);
1638*5c51f124SMoriah Waterland 
1639*5c51f124SMoriah Waterland 	/* zero out returned lock data */
1640*5c51f124SMoriah Waterland 
1641*5c51f124SMoriah Waterland 	bzero(pld, pls);
1642*5c51f124SMoriah Waterland 
1643*5c51f124SMoriah Waterland 	/* debug info before processing lock file */
1644*5c51f124SMoriah Waterland 
1645*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_FINDLOCK_ENTRY,
1646*5c51f124SMoriah Waterland 		a_object, a_key);
1647*5c51f124SMoriah Waterland 
1648*5c51f124SMoriah Waterland 	/* rewind to beginning of lock file */
1649*5c51f124SMoriah Waterland 
1650*5c51f124SMoriah Waterland 	pos = lseek(a_fd, 0L, SEEK_SET);
1651*5c51f124SMoriah Waterland 	if (pos == (off_t)-1) {
1652*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_FINDLOCK_LSEEK_FAILURE,
1653*5c51f124SMoriah Waterland 			a_object, a_key, strerror(errno));
1654*5c51f124SMoriah Waterland 		return (FINDLOCK_ERROR);
1655*5c51f124SMoriah Waterland 	}
1656*5c51f124SMoriah Waterland 
1657*5c51f124SMoriah Waterland 	/* read and process each lock */
1658*5c51f124SMoriah Waterland 
1659*5c51f124SMoriah Waterland 	for (; pread(a_fd, pld, pls, pls*recordNum) == pls; recordNum++) {
1660*5c51f124SMoriah Waterland 		/* debug info on this lock */
1661*5c51f124SMoriah Waterland 
1662*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LOCK_FINDLOCK_READRECORD,
1663*5c51f124SMoriah Waterland 			recordNum, pll->lockCount,
1664*5c51f124SMoriah Waterland 			pll->lockObject, pll->lockKey, pll->lockPid,
1665*5c51f124SMoriah Waterland 			pll->lockZoneId);
1666*5c51f124SMoriah Waterland 
1667*5c51f124SMoriah Waterland 		/* continue if object is not the one we are looking for */
1668*5c51f124SMoriah Waterland 
1669*5c51f124SMoriah Waterland 		if (_lockMatch(a_object, pll->lockObject) != 0) {
1670*5c51f124SMoriah Waterland 			continue;
1671*5c51f124SMoriah Waterland 		}
1672*5c51f124SMoriah Waterland 
1673*5c51f124SMoriah Waterland 		/*
1674*5c51f124SMoriah Waterland 		 * object found; return locked if searching for no key
1675*5c51f124SMoriah Waterland 		 */
1676*5c51f124SMoriah Waterland 
1677*5c51f124SMoriah Waterland 		if (*a_key == '\0') {
1678*5c51f124SMoriah Waterland 			/* no key specified - object is locked */
1679*5c51f124SMoriah Waterland 			*r_recordNum = recordNum;
1680*5c51f124SMoriah Waterland 			return (FINDLOCK_LOCKED);
1681*5c51f124SMoriah Waterland 		}
1682*5c51f124SMoriah Waterland 
1683*5c51f124SMoriah Waterland 		/*
1684*5c51f124SMoriah Waterland 		 * object found and keys present; see if keys match
1685*5c51f124SMoriah Waterland 		 */
1686*5c51f124SMoriah Waterland 
1687*5c51f124SMoriah Waterland 		if (strcmp(pll->lockKey, a_key) != 0) {
1688*5c51f124SMoriah Waterland 			/* keys do not match */
1689*5c51f124SMoriah Waterland 			*r_recordNum = recordNum;
1690*5c51f124SMoriah Waterland 			return (FINDLOCK_KEYMISMATCH);
1691*5c51f124SMoriah Waterland 		}
1692*5c51f124SMoriah Waterland 
1693*5c51f124SMoriah Waterland 		/* object found and keys match - return match */
1694*5c51f124SMoriah Waterland 
1695*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LOCK_FINDLOCK_FOUND);
1696*5c51f124SMoriah Waterland 
1697*5c51f124SMoriah Waterland 		*r_recordNum = recordNum;
1698*5c51f124SMoriah Waterland 		return (FINDLOCK_FOUND);
1699*5c51f124SMoriah Waterland 	}
1700*5c51f124SMoriah Waterland 
1701*5c51f124SMoriah Waterland 	/* object not locked - return error if key supplied */
1702*5c51f124SMoriah Waterland 
1703*5c51f124SMoriah Waterland 	if (*a_key != '\0') {
1704*5c51f124SMoriah Waterland 		return (FINDLOCK_NOTLOCKED);
1705*5c51f124SMoriah Waterland 	}
1706*5c51f124SMoriah Waterland 
1707*5c51f124SMoriah Waterland 	/* object not locked and key not supplied - no lock found */
1708*5c51f124SMoriah Waterland 
1709*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_FINDLOCK_NOTFOUND);
1710*5c51f124SMoriah Waterland 
1711*5c51f124SMoriah Waterland 	return (FINDLOCK_NOTFOUND);
1712*5c51f124SMoriah Waterland }
1713*5c51f124SMoriah Waterland 
1714*5c51f124SMoriah Waterland /*
1715*5c51f124SMoriah Waterland  * Name:	_addLock
1716*5c51f124SMoriah Waterland  * Description:	Add a new lock to the lock file
1717*5c51f124SMoriah Waterland  * Arguments:
1718*5c51f124SMoriah Waterland  *	r_key - if lock acquired key is placed here
1719*5c51f124SMoriah Waterland  *	a_fd - file descriptor opened on the lock file
1720*5c51f124SMoriah Waterland  *	a_object - object to lock
1721*5c51f124SMoriah Waterland  *	a_exclusive - type of lock to add:
1722*5c51f124SMoriah Waterland  *		== 0 - shared lock
1723*5c51f124SMoriah Waterland  *		!= 0 - exclusive lock
1724*5c51f124SMoriah Waterland  *	a_pid - if != 0 process i.d. to associate with this lock
1725*5c51f124SMoriah Waterland  *	a_zid - if >= 0 zone i.d. to associate with this lock
1726*5c51f124SMoriah Waterland  * Returns:	int
1727*5c51f124SMoriah Waterland  *			== 0 - success
1728*5c51f124SMoriah Waterland  *			!= 0 - failure
1729*5c51f124SMoriah Waterland  */
1730*5c51f124SMoriah Waterland 
1731*5c51f124SMoriah Waterland static int
1732*5c51f124SMoriah Waterland _addLock(char *r_key, int a_fd, char *a_object, int a_exclusive, pid_t a_pid,
1733*5c51f124SMoriah Waterland 	zoneid_t a_zid)
1734*5c51f124SMoriah Waterland {
1735*5c51f124SMoriah Waterland 	LOCK_T	theLock;
1736*5c51f124SMoriah Waterland 	char	*key;
1737*5c51f124SMoriah Waterland 	off_t	pos;
1738*5c51f124SMoriah Waterland 	ssize_t	result;
1739*5c51f124SMoriah Waterland 
1740*5c51f124SMoriah Waterland 	/* get unique i.d. for this lock */
1741*5c51f124SMoriah Waterland 
1742*5c51f124SMoriah Waterland 	key = _getUniqueId();
1743*5c51f124SMoriah Waterland 
1744*5c51f124SMoriah Waterland 	/* determine record number for next record in lock file */
1745*5c51f124SMoriah Waterland 
1746*5c51f124SMoriah Waterland 	pos = lseek(a_fd, 0L, SEEK_END);
1747*5c51f124SMoriah Waterland 	if (pos == (off_t)-1) {
1748*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_ADDLOCK_LSEEK_FAILURE,
1749*5c51f124SMoriah Waterland 			a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR,
1750*5c51f124SMoriah Waterland 			a_object, strerror(errno));
1751*5c51f124SMoriah Waterland 		return (1);
1752*5c51f124SMoriah Waterland 	}
1753*5c51f124SMoriah Waterland 
1754*5c51f124SMoriah Waterland 	/* allocate storace for this lock */
1755*5c51f124SMoriah Waterland 
1756*5c51f124SMoriah Waterland 	bzero(&theLock, sizeof (theLock));
1757*5c51f124SMoriah Waterland 
1758*5c51f124SMoriah Waterland 	/* fill in components of the lock */
1759*5c51f124SMoriah Waterland 
1760*5c51f124SMoriah Waterland 	(void) strlcpy(theLock._lrLock.lockObject, a_object,
1761*5c51f124SMoriah Waterland 							LOCK_OBJECT_MAXLEN);
1762*5c51f124SMoriah Waterland 	(void) strlcpy(theLock._lrLock.lockKey, key, LOCK_KEY_MAXLEN);
1763*5c51f124SMoriah Waterland 	theLock._lrLock.lockCount = 1;
1764*5c51f124SMoriah Waterland 	theLock._lrLock.lockPid = (a_pid > 0 ? a_pid : 0);
1765*5c51f124SMoriah Waterland 	theLock._lrLock.lockRecordNum = (pos == 0 ? 0 : (pos/sizeof (LOCK_T)));
1766*5c51f124SMoriah Waterland 	theLock._lrLock.lockExclusive = a_exclusive;
1767*5c51f124SMoriah Waterland 	theLock._lrLock.lockZoneId = (a_zid >= 0 ? a_zid : -1);
1768*5c51f124SMoriah Waterland 
1769*5c51f124SMoriah Waterland 	/* debug info on new lock */
1770*5c51f124SMoriah Waterland 
1771*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_ADDLOCK_ADDING,
1772*5c51f124SMoriah Waterland 		a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR,
1773*5c51f124SMoriah Waterland 		pos, theLock._lrLock.lockObject, theLock._lrLock.lockKey,
1774*5c51f124SMoriah Waterland 		theLock._lrLock.lockPid, theLock._lrLock.lockZoneId);
1775*5c51f124SMoriah Waterland 
1776*5c51f124SMoriah Waterland 	/* write the new lock record to the end of the lock file */
1777*5c51f124SMoriah Waterland 
1778*5c51f124SMoriah Waterland 	result = pwrite(a_fd, &theLock, LOCK_SIZE, pos);
1779*5c51f124SMoriah Waterland 	if (result != LOCK_SIZE) {
1780*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_ADDLOCK_PWRITE_FAILURE,
1781*5c51f124SMoriah Waterland 			a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR,
1782*5c51f124SMoriah Waterland 			a_object, strerror(errno));
1783*5c51f124SMoriah Waterland 		return (1);
1784*5c51f124SMoriah Waterland 	}
1785*5c51f124SMoriah Waterland 
1786*5c51f124SMoriah Waterland 	/* output the key assigned to standard out */
1787*5c51f124SMoriah Waterland 
1788*5c51f124SMoriah Waterland 	(void) strncpy(r_key, key, LOCK_KEY_MAXLEN);
1789*5c51f124SMoriah Waterland 
1790*5c51f124SMoriah Waterland 	return (0);
1791*5c51f124SMoriah Waterland }
1792*5c51f124SMoriah Waterland 
1793*5c51f124SMoriah Waterland static int
1794*5c51f124SMoriah Waterland _incrementLockCount(int a_fd, LOCK_T *a_theLock)
1795*5c51f124SMoriah Waterland {
1796*5c51f124SMoriah Waterland 	ADMINLOCK_T	*pll;
1797*5c51f124SMoriah Waterland 	char		*pld;
1798*5c51f124SMoriah Waterland 	long		pls;
1799*5c51f124SMoriah Waterland 	ssize_t		result;
1800*5c51f124SMoriah Waterland 
1801*5c51f124SMoriah Waterland 	/* localize references to lock object */
1802*5c51f124SMoriah Waterland 
1803*5c51f124SMoriah Waterland 	pld = &a_theLock->_lrLockData[0];
1804*5c51f124SMoriah Waterland 	pll = &a_theLock->_lrLock;
1805*5c51f124SMoriah Waterland 	pls = sizeof (a_theLock->_lrLockData);
1806*5c51f124SMoriah Waterland 
1807*5c51f124SMoriah Waterland 	/* debug info on incrementing lock */
1808*5c51f124SMoriah Waterland 
1809*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_INCLOCK_ENTRY,
1810*5c51f124SMoriah Waterland 		a_theLock->_lrLock.lockExclusive ?
1811*5c51f124SMoriah Waterland 				MSG_LOCK_EXC : MSG_LOCK_SHR,
1812*5c51f124SMoriah Waterland 		pll->lockRecordNum, pll->lockCount);
1813*5c51f124SMoriah Waterland 
1814*5c51f124SMoriah Waterland 	/* increment lock count */
1815*5c51f124SMoriah Waterland 
1816*5c51f124SMoriah Waterland 	pll->lockCount++;
1817*5c51f124SMoriah Waterland 
1818*5c51f124SMoriah Waterland 	/* write out updated lock */
1819*5c51f124SMoriah Waterland 
1820*5c51f124SMoriah Waterland 	result = pwrite(a_fd, pld, pls, pll->lockRecordNum*pls);
1821*5c51f124SMoriah Waterland 	if (result != pls) {
1822*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_INCLOCK_PWRITE_FAILURE,
1823*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockExclusive ?
1824*5c51f124SMoriah Waterland 					MSG_LOCK_EXC : MSG_LOCK_SHR,
1825*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockObject,
1826*5c51f124SMoriah Waterland 			strerror(errno));
1827*5c51f124SMoriah Waterland 		return (1);
1828*5c51f124SMoriah Waterland 	}
1829*5c51f124SMoriah Waterland 
1830*5c51f124SMoriah Waterland 	/* debug info lock incremented */
1831*5c51f124SMoriah Waterland 
1832*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_INCLOCK_DONE,
1833*5c51f124SMoriah Waterland 		pll->lockRecordNum, pll->lockCount,
1834*5c51f124SMoriah Waterland 		pll->lockObject, pll->lockKey);
1835*5c51f124SMoriah Waterland 
1836*5c51f124SMoriah Waterland 	return (0);
1837*5c51f124SMoriah Waterland }
1838*5c51f124SMoriah Waterland 
1839*5c51f124SMoriah Waterland /*
1840*5c51f124SMoriah Waterland  * Name:	_validateLock
1841*5c51f124SMoriah Waterland  * Description:	determine if a specified lock is valid; if the lock is not valid
1842*5c51f124SMoriah Waterland  *		then remove the lock
1843*5c51f124SMoriah Waterland  * Arguments:	a_fd - file descriptor opened on the lock file
1844*5c51f124SMoriah Waterland  *		a_theLock - lock object to validate
1845*5c51f124SMoriah Waterland  * Returns:	boolean_t
1846*5c51f124SMoriah Waterland  *			B_TRUE - the lock is valid
1847*5c51f124SMoriah Waterland  *			B_FALSE - the lock is not valid and has been removed
1848*5c51f124SMoriah Waterland  */
1849*5c51f124SMoriah Waterland 
1850*5c51f124SMoriah Waterland static boolean_t
1851*5c51f124SMoriah Waterland _validateLock(int a_fd, LOCK_T *a_theLock, int a_quiet)
1852*5c51f124SMoriah Waterland {
1853*5c51f124SMoriah Waterland 	ADMINLOCK_T	*pll;
1854*5c51f124SMoriah Waterland 	char		*pld;
1855*5c51f124SMoriah Waterland 	long		pls;
1856*5c51f124SMoriah Waterland 	char		path[MAXPATHLEN];
1857*5c51f124SMoriah Waterland 
1858*5c51f124SMoriah Waterland 	/* localize references to lock object */
1859*5c51f124SMoriah Waterland 
1860*5c51f124SMoriah Waterland 	pld = &a_theLock->_lrLockData[0];
1861*5c51f124SMoriah Waterland 	pll = &a_theLock->_lrLock;
1862*5c51f124SMoriah Waterland 	pls = sizeof (a_theLock->_lrLockData);
1863*5c51f124SMoriah Waterland 
1864*5c51f124SMoriah Waterland 	/* return true if no process i.d. associated with lock */
1865*5c51f124SMoriah Waterland 
1866*5c51f124SMoriah Waterland 	if (pll->lockPid <= 0) {
1867*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_VALID_NOPID, pll->lockObject);
1868*5c51f124SMoriah Waterland 		return (B_TRUE);
1869*5c51f124SMoriah Waterland 	}
1870*5c51f124SMoriah Waterland 
1871*5c51f124SMoriah Waterland 	/* see if the zone i.d. matches */
1872*5c51f124SMoriah Waterland 
1873*5c51f124SMoriah Waterland 	if (pll->lockZoneId != getzoneid()) {
1874*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_VALID_BADZID, pll->lockObject,
1875*5c51f124SMoriah Waterland 		pll->lockZoneId, getzoneid());
1876*5c51f124SMoriah Waterland 		return (B_TRUE);
1877*5c51f124SMoriah Waterland 	} else {
1878*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_VALID_ZIDOK, pll->lockObject,
1879*5c51f124SMoriah Waterland 		pll->lockZoneId, getzoneid());
1880*5c51f124SMoriah Waterland 	}
1881*5c51f124SMoriah Waterland 
1882*5c51f124SMoriah Waterland 	/* see if the process is still active */
1883*5c51f124SMoriah Waterland 
1884*5c51f124SMoriah Waterland 	pkgstrPrintf_r(path, sizeof (path), "/proc/%d", pll->lockPid);
1885*5c51f124SMoriah Waterland 	if (access(path, F_OK) == 0) {
1886*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_VALID_OK, pll->lockObject,
1887*5c51f124SMoriah Waterland 			pll->lockPid, path);
1888*5c51f124SMoriah Waterland 		return (B_TRUE);
1889*5c51f124SMoriah Waterland 	}
1890*5c51f124SMoriah Waterland 
1891*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_VALID_NOTOK, pll->lockObject, pll->lockPid,
1892*5c51f124SMoriah Waterland 		path);
1893*5c51f124SMoriah Waterland 
1894*5c51f124SMoriah Waterland 	/* delete this lock */
1895*5c51f124SMoriah Waterland 
1896*5c51f124SMoriah Waterland 	log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_WRN,
1897*5c51f124SMoriah Waterland 		MSG_VALID_STALE, pll->lockObject, pll->lockPid,
1898*5c51f124SMoriah Waterland 		pll->lockZoneId);
1899*5c51f124SMoriah Waterland 
1900*5c51f124SMoriah Waterland 	_decrementLockCount(a_fd, a_theLock);
1901*5c51f124SMoriah Waterland 
1902*5c51f124SMoriah Waterland 	return (B_FALSE);
1903*5c51f124SMoriah Waterland }
1904*5c51f124SMoriah Waterland 
1905*5c51f124SMoriah Waterland static int
1906*5c51f124SMoriah Waterland _decrementLockCount(int a_fd, LOCK_T *a_theLock)
1907*5c51f124SMoriah Waterland {
1908*5c51f124SMoriah Waterland 	ADMINLOCK_T	*pll;
1909*5c51f124SMoriah Waterland 	LOCK_T		tmpLock;
1910*5c51f124SMoriah Waterland 	RECORDNUM_T	lastRecord;
1911*5c51f124SMoriah Waterland 	char		*pld;
1912*5c51f124SMoriah Waterland 	long		pls;
1913*5c51f124SMoriah Waterland 	off_t		lastPos;
1914*5c51f124SMoriah Waterland 	ssize_t		result;
1915*5c51f124SMoriah Waterland 	int		res;
1916*5c51f124SMoriah Waterland 
1917*5c51f124SMoriah Waterland 	/* localize references to lock object */
1918*5c51f124SMoriah Waterland 
1919*5c51f124SMoriah Waterland 	pld = &a_theLock->_lrLockData[0];
1920*5c51f124SMoriah Waterland 	pll = &a_theLock->_lrLock;
1921*5c51f124SMoriah Waterland 	pls = sizeof (a_theLock->_lrLockData);
1922*5c51f124SMoriah Waterland 
1923*5c51f124SMoriah Waterland 	/* decrement lock count */
1924*5c51f124SMoriah Waterland 
1925*5c51f124SMoriah Waterland 	pll->lockCount--;
1926*5c51f124SMoriah Waterland 
1927*5c51f124SMoriah Waterland 	/* if lock count > 0 then write out and leave locked */
1928*5c51f124SMoriah Waterland 
1929*5c51f124SMoriah Waterland 	if (pll->lockCount > 0) {
1930*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LOCK_DECLOCK_DECING,
1931*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockExclusive ?
1932*5c51f124SMoriah Waterland 				MSG_LOCK_EXC : MSG_LOCK_SHR,
1933*5c51f124SMoriah Waterland 			pll->lockRecordNum, pll->lockCount);
1934*5c51f124SMoriah Waterland 
1935*5c51f124SMoriah Waterland 		result = pwrite(a_fd, pld, pls, pll->lockRecordNum*pls);
1936*5c51f124SMoriah Waterland 		if (result != pls) {
1937*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_PWRITE_FAILURE,
1938*5c51f124SMoriah Waterland 				a_theLock->_lrLock.lockExclusive ?
1939*5c51f124SMoriah Waterland 						MSG_LOCK_EXC : MSG_LOCK_SHR,
1940*5c51f124SMoriah Waterland 				a_theLock->_lrLock.lockObject,
1941*5c51f124SMoriah Waterland 				strerror(errno));
1942*5c51f124SMoriah Waterland 			return (1);
1943*5c51f124SMoriah Waterland 		}
1944*5c51f124SMoriah Waterland 
1945*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LOCK_DECLOCK_DONE,
1946*5c51f124SMoriah Waterland 			pll->lockRecordNum, pll->lockCount,
1947*5c51f124SMoriah Waterland 			pll->lockObject, pll->lockKey);
1948*5c51f124SMoriah Waterland 
1949*5c51f124SMoriah Waterland 		return (0);
1950*5c51f124SMoriah Waterland 	}
1951*5c51f124SMoriah Waterland 
1952*5c51f124SMoriah Waterland 	/*
1953*5c51f124SMoriah Waterland 	 * lock count zero - erase the record
1954*5c51f124SMoriah Waterland 	 */
1955*5c51f124SMoriah Waterland 
1956*5c51f124SMoriah Waterland 	/* find last record in the lock file */
1957*5c51f124SMoriah Waterland 
1958*5c51f124SMoriah Waterland 	lastPos = lseek(a_fd, 0L, SEEK_END);	/* get size of lock file */
1959*5c51f124SMoriah Waterland 	if (lastPos == (off_t)-1) {
1960*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_LSEEK_FAILURE,
1961*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockExclusive ?
1962*5c51f124SMoriah Waterland 					MSG_LOCK_EXC : MSG_LOCK_SHR,
1963*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockObject,
1964*5c51f124SMoriah Waterland 			strerror(errno));
1965*5c51f124SMoriah Waterland 		return (1);
1966*5c51f124SMoriah Waterland 	}
1967*5c51f124SMoriah Waterland 
1968*5c51f124SMoriah Waterland 	lastRecord = (lastPos/pls)-1;	/* convert size to record # */
1969*5c51f124SMoriah Waterland 
1970*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_DECLOCK_REMOVE,
1971*5c51f124SMoriah Waterland 		lastPos, lastRecord, pll->lockRecordNum);
1972*5c51f124SMoriah Waterland 
1973*5c51f124SMoriah Waterland 	/* see if removing last record of file */
1974*5c51f124SMoriah Waterland 
1975*5c51f124SMoriah Waterland 	if (lastRecord == pll->lockRecordNum) {
1976*5c51f124SMoriah Waterland 		/* debug info removing last record */
1977*5c51f124SMoriah Waterland 
1978*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LOCK_DECLOCK_LASTONE,
1979*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockExclusive ?
1980*5c51f124SMoriah Waterland 				MSG_LOCK_EXC : MSG_LOCK_SHR,
1981*5c51f124SMoriah Waterland 			lastRecord, lastPos-pls);
1982*5c51f124SMoriah Waterland 
1983*5c51f124SMoriah Waterland 		/* removing last record of file, truncate */
1984*5c51f124SMoriah Waterland 
1985*5c51f124SMoriah Waterland 		res = ftruncate(a_fd, lastPos-pls);
1986*5c51f124SMoriah Waterland 		if (res == -1) {
1987*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_FTRUNCATE_FAILURE,
1988*5c51f124SMoriah Waterland 				a_theLock->_lrLock.lockExclusive ?
1989*5c51f124SMoriah Waterland 						MSG_LOCK_EXC : MSG_LOCK_SHR,
1990*5c51f124SMoriah Waterland 				a_theLock->_lrLock.lockObject,
1991*5c51f124SMoriah Waterland 				strerror(errno));
1992*5c51f124SMoriah Waterland 				return (1);
1993*5c51f124SMoriah Waterland 		}
1994*5c51f124SMoriah Waterland 		return (0);
1995*5c51f124SMoriah Waterland 	}
1996*5c51f124SMoriah Waterland 
1997*5c51f124SMoriah Waterland 	/*
1998*5c51f124SMoriah Waterland 	 * not removing last record of file:
1999*5c51f124SMoriah Waterland 	 * read last record, truncate file one record,
2000*5c51f124SMoriah Waterland 	 * replace record to be removed with last record read
2001*5c51f124SMoriah Waterland 	 */
2002*5c51f124SMoriah Waterland 
2003*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_DECLOCK_REMOVING,
2004*5c51f124SMoriah Waterland 		pll->lockRecordNum, lastRecord, lastPos-pls);
2005*5c51f124SMoriah Waterland 
2006*5c51f124SMoriah Waterland 	/* read in the last record */
2007*5c51f124SMoriah Waterland 
2008*5c51f124SMoriah Waterland 	result = pread(a_fd, tmpLock._lrLockData, pls, lastRecord*pls);
2009*5c51f124SMoriah Waterland 	if (result != pls) {
2010*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_PREAD_FAILURE,
2011*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockExclusive ?
2012*5c51f124SMoriah Waterland 					MSG_LOCK_EXC : MSG_LOCK_SHR,
2013*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockObject,
2014*5c51f124SMoriah Waterland 			strerror(errno));
2015*5c51f124SMoriah Waterland 		return (1);
2016*5c51f124SMoriah Waterland 
2017*5c51f124SMoriah Waterland 	}
2018*5c51f124SMoriah Waterland 
2019*5c51f124SMoriah Waterland 	/* truncate lock file removing the last record (just read in) */
2020*5c51f124SMoriah Waterland 
2021*5c51f124SMoriah Waterland 	res = ftruncate(a_fd, lastPos-pls);
2022*5c51f124SMoriah Waterland 	if (res == -1) {
2023*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_FTRUNCATE_FAILURE,
2024*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockExclusive ?
2025*5c51f124SMoriah Waterland 					MSG_LOCK_EXC : MSG_LOCK_SHR,
2026*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockObject,
2027*5c51f124SMoriah Waterland 			strerror(errno));
2028*5c51f124SMoriah Waterland 			return (1);
2029*5c51f124SMoriah Waterland 	}
2030*5c51f124SMoriah Waterland 
2031*5c51f124SMoriah Waterland 	/* update record to indicate its new position in the lock file */
2032*5c51f124SMoriah Waterland 
2033*5c51f124SMoriah Waterland 	tmpLock._lrLock.lockRecordNum = pll->lockRecordNum;
2034*5c51f124SMoriah Waterland 
2035*5c51f124SMoriah Waterland 	/* write out the updated record to the new location */
2036*5c51f124SMoriah Waterland 
2037*5c51f124SMoriah Waterland 	result = pwrite(a_fd, tmpLock._lrLockData, pls, pll->lockRecordNum*pls);
2038*5c51f124SMoriah Waterland 	if (result != pls) {
2039*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_PWRITE_FAILURE,
2040*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockExclusive ?
2041*5c51f124SMoriah Waterland 					MSG_LOCK_EXC : MSG_LOCK_SHR,
2042*5c51f124SMoriah Waterland 			a_theLock->_lrLock.lockObject,
2043*5c51f124SMoriah Waterland 			strerror(errno));
2044*5c51f124SMoriah Waterland 		return (1);
2045*5c51f124SMoriah Waterland 	}
2046*5c51f124SMoriah Waterland 
2047*5c51f124SMoriah Waterland 	return (0);
2048*5c51f124SMoriah Waterland }
2049*5c51f124SMoriah Waterland 
2050*5c51f124SMoriah Waterland /*
2051*5c51f124SMoriah Waterland  * Name:	_getUniqueId
2052*5c51f124SMoriah Waterland  * Description:	Generate a unique ID that can be used as a key for a new lock
2053*5c51f124SMoriah Waterland  * Arguments:	None
2054*5c51f124SMoriah Waterland  * Returns:	char *
2055*5c51f124SMoriah Waterland  *			== NULL - error, no key generated
2056*5c51f124SMoriah Waterland  *			!= NULL - generated key
2057*5c51f124SMoriah Waterland  * NOTE:    	Any results returned is placed in new storage for the
2058*5c51f124SMoriah Waterland  *		calling method. The caller must use 'lu_memFree' to dispose
2059*5c51f124SMoriah Waterland  *		of the storage once the results are no longer needed.
2060*5c51f124SMoriah Waterland  */
2061*5c51f124SMoriah Waterland 
2062*5c51f124SMoriah Waterland static char *
2063*5c51f124SMoriah Waterland _getUniqueId(void)
2064*5c51f124SMoriah Waterland {
2065*5c51f124SMoriah Waterland 	char		*args[10];
2066*5c51f124SMoriah Waterland 	char		*execResults;
2067*5c51f124SMoriah Waterland 	char		newkey[LOCK_KEY_MAXLEN];
2068*5c51f124SMoriah Waterland 	hrtime_t	hretime;
2069*5c51f124SMoriah Waterland 	int		b;
2070*5c51f124SMoriah Waterland 	int		execStatus;
2071*5c51f124SMoriah Waterland 	struct tm	tstruct;
2072*5c51f124SMoriah Waterland 	time_t		thetime;
2073*5c51f124SMoriah Waterland 
2074*5c51f124SMoriah Waterland 	/*
2075*5c51f124SMoriah Waterland 	 * try and use makeuuid to generate a unique i.d. Such a unique i.d.
2076*5c51f124SMoriah Waterland 	 * will look like:
2077*5c51f124SMoriah Waterland 	 *		7814e3c1-1dd2-11b2-9fe8-000d560ddc82
2078*5c51f124SMoriah Waterland 	 */
2079*5c51f124SMoriah Waterland 
2080*5c51f124SMoriah Waterland 	args[0] = "makeuuid";
2081*5c51f124SMoriah Waterland 	args[1] = (char *)NULL;
2082*5c51f124SMoriah Waterland 
2083*5c51f124SMoriah Waterland 	b = e_ExecCmdList(&execStatus, &execResults, (char *)NULL,
2084*5c51f124SMoriah Waterland 		"/usr/bin/makeuuid", (char *)NULL);
2085*5c51f124SMoriah Waterland 
2086*5c51f124SMoriah Waterland 	if ((b == 0) && (execStatus == 0) && (*execResults != '\0')) {
2087*5c51f124SMoriah Waterland 		char	*p;
2088*5c51f124SMoriah Waterland 		p = strpbrk(execResults, " \t\n");
2089*5c51f124SMoriah Waterland 		if (p != (char *)NULL) {
2090*5c51f124SMoriah Waterland 			*p = '\0';
2091*5c51f124SMoriah Waterland 		}
2092*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, MSG_LOCK_GENUID_MAKEUUID,
2093*5c51f124SMoriah Waterland 			execResults);
2094*5c51f124SMoriah Waterland 		return (execResults);
2095*5c51f124SMoriah Waterland 	}
2096*5c51f124SMoriah Waterland 
2097*5c51f124SMoriah Waterland 	/*
2098*5c51f124SMoriah Waterland 	 * cannot run makeuuid - generate own unique key - the key is the
2099*5c51f124SMoriah Waterland 	 * same length as unique uid but contains different information that
2100*5c51f124SMoriah Waterland 	 * is as unique as can be made - include current hires time (nanosecond
2101*5c51f124SMoriah Waterland 	 * real timer. Such a unique i.d. will look like:
2102*5c51f124SMoriah Waterland 	 *		0203104092-1145345-0004e94d6af481a0
2103*5c51f124SMoriah Waterland 	 */
2104*5c51f124SMoriah Waterland 
2105*5c51f124SMoriah Waterland 	hretime = gethrtime();
2106*5c51f124SMoriah Waterland 
2107*5c51f124SMoriah Waterland 	thetime = time((time_t *)NULL);
2108*5c51f124SMoriah Waterland 	(void) localtime_r(&thetime, &tstruct);
2109*5c51f124SMoriah Waterland 
2110*5c51f124SMoriah Waterland 	(void) snprintf(newkey, sizeof (newkey),
2111*5c51f124SMoriah Waterland 		"%02d%02d%02d%03d-%02d%02d%02d%d-%016llx", tstruct.tm_mday,
2112*5c51f124SMoriah Waterland 		tstruct.tm_mon, tstruct.tm_year, tstruct.tm_yday,
2113*5c51f124SMoriah Waterland 		tstruct.tm_hour, tstruct.tm_min, tstruct.tm_sec,
2114*5c51f124SMoriah Waterland 		tstruct.tm_wday, hretime);
2115*5c51f124SMoriah Waterland 
2116*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, MSG_LOCK_GENUID_INTERNAL, newkey);
2117*5c51f124SMoriah Waterland 	return (strdup(newkey));
2118*5c51f124SMoriah Waterland }
2119*5c51f124SMoriah Waterland 
2120*5c51f124SMoriah Waterland /*
2121*5c51f124SMoriah Waterland  * Name:	sigint_handler
2122*5c51f124SMoriah Waterland  * Synopsis:	SIGINT interrupt handler
2123*5c51f124SMoriah Waterland  * Description:	Catch the "SIGINT" signal; increment signal_received
2124*5c51f124SMoriah Waterland  *		global variable,
2125*5c51f124SMoriah Waterland  * Arguments:	signo - [RO, *RO] - (int)
2126*5c51f124SMoriah Waterland  *			Signal number that was caught
2127*5c51f124SMoriah Waterland  * Returns:	void
2128*5c51f124SMoriah Waterland  */
2129*5c51f124SMoriah Waterland 
2130*5c51f124SMoriah Waterland static void
2131*5c51f124SMoriah Waterland sigint_handler(int a_signo)
2132*5c51f124SMoriah Waterland {
2133*5c51f124SMoriah Waterland 	signal_received++;
2134*5c51f124SMoriah Waterland }
2135*5c51f124SMoriah Waterland 
2136*5c51f124SMoriah Waterland /*
2137*5c51f124SMoriah Waterland  * Name:	sighup_handler
2138*5c51f124SMoriah Waterland  * Synopsis:	SIGHUP interrupt handler
2139*5c51f124SMoriah Waterland  * Description:	Catch the "SIGHUP" signal; increment signal_received
2140*5c51f124SMoriah Waterland  *		global variable,
2141*5c51f124SMoriah Waterland  * Arguments:	signo - [RO, *RO] - (int)
2142*5c51f124SMoriah Waterland  *			Signal number that was caught
2143*5c51f124SMoriah Waterland  * Returns:	void
2144*5c51f124SMoriah Waterland  */
2145*5c51f124SMoriah Waterland 
2146*5c51f124SMoriah Waterland static void
2147*5c51f124SMoriah Waterland sighup_handler(int a_signo)
2148*5c51f124SMoriah Waterland {
2149*5c51f124SMoriah Waterland 	signal_received++;
2150*5c51f124SMoriah Waterland }
2151