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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 2147 sighup_handler(int a_signo) 2148 { 2149 signal_received++; 2150 } 2151