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