15c51f124SMoriah Waterland /* 25c51f124SMoriah Waterland * CDDL HEADER START 35c51f124SMoriah Waterland * 45c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 55c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 65c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 75c51f124SMoriah Waterland * 85c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 105c51f124SMoriah Waterland * See the License for the specific language governing permissions 115c51f124SMoriah Waterland * and limitations under the License. 125c51f124SMoriah Waterland * 135c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 145c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 165c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 175c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 185c51f124SMoriah Waterland * 195c51f124SMoriah Waterland * CDDL HEADER END 205c51f124SMoriah Waterland */ 215c51f124SMoriah Waterland 2232991bedSPeter Tribble /* 2332991bedSPeter Tribble * Copyright (c) 2017 Peter Tribble. 2432991bedSPeter Tribble */ 2532991bedSPeter Tribble 265c51f124SMoriah Waterland /* 275c51f124SMoriah Waterland * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 285c51f124SMoriah Waterland * Use is subject to license terms. 295c51f124SMoriah Waterland */ 305c51f124SMoriah Waterland 315c51f124SMoriah Waterland 325c51f124SMoriah Waterland /* 335c51f124SMoriah Waterland * Module: lock.c 345c51f124SMoriah Waterland * Program: pkgadm (/usr/bin/pkgadm) 355c51f124SMoriah Waterland * Synopsis: implements the zone/package administrative lock interface 365c51f124SMoriah Waterland * Public methods: 375c51f124SMoriah Waterland * admin_lock 385c51f124SMoriah Waterland * Usage: 395c51f124SMoriah Waterland * Acquire: -a [ -e | -s ] [ -o obj ] [ -k key ] [ -R root ] [ -q ] \ 405c51f124SMoriah Waterland * [ -w ] [ -W timeout ] 415c51f124SMoriah Waterland * Release: -r -o object -k key [ -R altRoot ] [ -q ] 425c51f124SMoriah Waterland * Status: [ -o object ] [ -k key ] [ -R altRoot ] [ -q ] 435c51f124SMoriah Waterland */ 445c51f124SMoriah Waterland 455c51f124SMoriah Waterland /* enable extentions to standard Unix libraries */ 465c51f124SMoriah Waterland 475c51f124SMoriah Waterland #define __EXTENSIONS__ 485c51f124SMoriah Waterland 495c51f124SMoriah Waterland /* unix system includes */ 505c51f124SMoriah Waterland 515c51f124SMoriah Waterland #include <stdio.h> 525c51f124SMoriah Waterland #include <stdarg.h> 535c51f124SMoriah Waterland #include <stdlib.h> 545c51f124SMoriah Waterland #include <string.h> 555c51f124SMoriah Waterland #include <strings.h> 565c51f124SMoriah Waterland #include <sys/types.h> 575c51f124SMoriah Waterland #include <wait.h> 585c51f124SMoriah Waterland #include <sys/stat.h> 595c51f124SMoriah Waterland #include <fcntl.h> 605c51f124SMoriah Waterland #include <unistd.h> 615c51f124SMoriah Waterland #include <signal.h> 625c51f124SMoriah Waterland #include <locale.h> 635c51f124SMoriah Waterland #include <libgen.h> 645c51f124SMoriah Waterland #include <sys/param.h> 655c51f124SMoriah Waterland #include <errno.h> 665c51f124SMoriah Waterland #include <assert.h> 675c51f124SMoriah Waterland #include <time.h> 685c51f124SMoriah Waterland #include <fnmatch.h> 695c51f124SMoriah Waterland #include <zone.h> 705c51f124SMoriah Waterland 715c51f124SMoriah Waterland /* local includes */ 725c51f124SMoriah Waterland 735c51f124SMoriah Waterland #include <libinst.h> 745c51f124SMoriah Waterland #include <pkglib.h> 755c51f124SMoriah Waterland #include "pkgadm.h" 765c51f124SMoriah Waterland #include "pkgadm_msgs.h" 775c51f124SMoriah Waterland 785c51f124SMoriah Waterland /* definition and conversion of sleep units */ 795c51f124SMoriah Waterland 805c51f124SMoriah Waterland #define SECONDS(x) ((unsigned int)(x)) 815c51f124SMoriah Waterland #define MINUTES(x) ((unsigned int)(seconds(x)*60)) 825c51f124SMoriah Waterland 835c51f124SMoriah Waterland /* define how waits are timed */ 845c51f124SMoriah Waterland 855c51f124SMoriah Waterland #define WAITER_INITIAL SECONDS(1) 865c51f124SMoriah Waterland #define WAITER_MAX SECONDS(60) 875c51f124SMoriah Waterland #define WAITER_NEXT(x) ((x)*2) 885c51f124SMoriah Waterland 895c51f124SMoriah Waterland typedef unsigned int WAITER_T; 905c51f124SMoriah Waterland 915c51f124SMoriah Waterland /* 925c51f124SMoriah Waterland * The administrative lock file resides in /tmp 935c51f124SMoriah Waterland * It does not survive a reboot 945c51f124SMoriah Waterland * It consists of fixed length records 955c51f124SMoriah Waterland * Each record has the following information: 965c51f124SMoriah Waterland * record number - record position within the lock file 975c51f124SMoriah Waterland * lock count - number of lock holders maintaining this lock 985c51f124SMoriah Waterland * lock object - object being locked 995c51f124SMoriah Waterland * lock key - key needed to manipulate existing lock 1005c51f124SMoriah Waterland * lock exclusive - is the lock exclusive (single locker only) 1015c51f124SMoriah Waterland */ 1025c51f124SMoriah Waterland 1035c51f124SMoriah Waterland #define LOCK_OBJECT_MAXLEN 512-1 1045c51f124SMoriah Waterland #define LOCK_KEY_MAXLEN 37 1055c51f124SMoriah Waterland 1065c51f124SMoriah Waterland #define LOCK_DIRECTORY "/tmp" 1075c51f124SMoriah Waterland 1085c51f124SMoriah Waterland /* 1095c51f124SMoriah Waterland * this is the "well known name" of the lock file that is used by the 1105c51f124SMoriah Waterland * package, patch, and zone administration commands to synchronize their 1115c51f124SMoriah Waterland * various efforts - it must live in a temporary directory that is cleared 1125c51f124SMoriah Waterland * on system reboot but it is NOT a temporary file in that it survives 1135c51f124SMoriah Waterland * the process that creates and updates it - if the format of the lock 1145c51f124SMoriah Waterland * file ever changes, this path should be updated with a later "uuid" 1155c51f124SMoriah Waterland * so that previous (incompatible) pkgadm's will not use the later data. 1165c51f124SMoriah Waterland */ 1175c51f124SMoriah Waterland 1185c51f124SMoriah Waterland #define LOCK_FILENAME \ 1195c51f124SMoriah Waterland "/tmp/.ai.pkg.zone.lock-afdb66cf-1dd1-11b2-a049-000d560ddc3e" 1205c51f124SMoriah Waterland 1215c51f124SMoriah Waterland /* mode to use for LOCK_FILENAME */ 1225c51f124SMoriah Waterland 1235c51f124SMoriah Waterland #define LOCK_FILEMODE \ 1245c51f124SMoriah Waterland (S_ISGID|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 1255c51f124SMoriah Waterland 1265c51f124SMoriah Waterland #define LOCK_SLEEP_INTERVAL SECONDS(2) 1275c51f124SMoriah Waterland 1285c51f124SMoriah Waterland /* lock contents types */ 1295c51f124SMoriah Waterland 1305c51f124SMoriah Waterland typedef unsigned long RECORDNUM_T; 1315c51f124SMoriah Waterland 1325c51f124SMoriah Waterland #define RECORDNUM_NONE 0xFFFFFFFF 1335c51f124SMoriah Waterland 1345c51f124SMoriah Waterland /* actual lock data */ 1355c51f124SMoriah Waterland 1365c51f124SMoriah Waterland struct _adminLock 1375c51f124SMoriah Waterland { 1385c51f124SMoriah Waterland RECORDNUM_T lockRecordNum; 1395c51f124SMoriah Waterland unsigned long lockCount; 1405c51f124SMoriah Waterland unsigned long lockExclusive; 1415c51f124SMoriah Waterland pid_t lockPid; 1425c51f124SMoriah Waterland zoneid_t lockZoneId; 1435c51f124SMoriah Waterland char lockKey[LOCK_KEY_MAXLEN+1]; 1445c51f124SMoriah Waterland char lockObject[LOCK_OBJECT_MAXLEN+1]; 1455c51f124SMoriah Waterland }; 1465c51f124SMoriah Waterland 1475c51f124SMoriah Waterland typedef struct _adminLock ADMINLOCK_T; 1485c51f124SMoriah Waterland 1495c51f124SMoriah Waterland /* size of an individual "lock" */ 1505c51f124SMoriah Waterland 1515c51f124SMoriah Waterland #define LOCK_SIZE sizeof (ADMINLOCK_T) 1525c51f124SMoriah Waterland 1535c51f124SMoriah Waterland /* union to allow lock to be accessed as raw or structured data */ 1545c51f124SMoriah Waterland 1555c51f124SMoriah Waterland union _lockRecord 1565c51f124SMoriah Waterland { 1575c51f124SMoriah Waterland char _lrLockData[LOCK_SIZE]; 1585c51f124SMoriah Waterland ADMINLOCK_T _lrLock; 1595c51f124SMoriah Waterland }; 1605c51f124SMoriah Waterland 1615c51f124SMoriah Waterland typedef union _lockRecord LOCK_T; 1625c51f124SMoriah Waterland 1635c51f124SMoriah Waterland /* return codes from "_findLock" */ 1645c51f124SMoriah Waterland 1655c51f124SMoriah Waterland typedef unsigned long FINDLOCK_T; 1665c51f124SMoriah Waterland 1675c51f124SMoriah Waterland #define FINDLOCK_FOUND ((FINDLOCK_T)0) 1685c51f124SMoriah Waterland #define FINDLOCK_ERROR ((FINDLOCK_T)-1) 1695c51f124SMoriah Waterland #define FINDLOCK_NOTFOUND ((FINDLOCK_T)-2) 1705c51f124SMoriah Waterland #define FINDLOCK_KEYMISMATCH ((FINDLOCK_T)-3) 1715c51f124SMoriah Waterland #define FINDLOCK_LOCKED ((FINDLOCK_T)-4) 1725c51f124SMoriah Waterland #define FINDLOCK_NOTLOCKED ((FINDLOCK_T)-5) 1735c51f124SMoriah Waterland #define FINDLOCK_LOCKACQUIRED ((FINDLOCK_T)-6) 1745c51f124SMoriah Waterland 1755c51f124SMoriah Waterland /* 1765c51f124SMoriah Waterland * Forward declarations 1775c51f124SMoriah Waterland */ 1785c51f124SMoriah Waterland 1795c51f124SMoriah Waterland /* local main function implementation methods */ 1805c51f124SMoriah Waterland 1815c51f124SMoriah Waterland static FINDLOCK_T lock_acquire(LOCK_T *a_lock, int *a_fd, char *a_root, 1825c51f124SMoriah Waterland char *a_key, char *a_object, int a_quiet, 1835c51f124SMoriah Waterland int a_wait, long a_timeout, int a_exclusive, 1845c51f124SMoriah Waterland char *a_altRoot, pid_t a_pid, zoneid_t a_zid); 1855c51f124SMoriah Waterland static int lock_release(int a_fd, char *a_key, char *a_object, 1865c51f124SMoriah Waterland int a_quiet); 1875c51f124SMoriah Waterland static int lock_status(int a_fd, char *a_key, char *a_object, 1885c51f124SMoriah Waterland int a_quiet); 1895c51f124SMoriah Waterland 1905c51f124SMoriah Waterland /* local utility functions */ 1915c51f124SMoriah Waterland 1925c51f124SMoriah Waterland static int _lockMatch(char *a_s1Lock, char *a_s2Lock); 1935c51f124SMoriah Waterland static FINDLOCK_T _findLock(LOCK_T *a_theLock, RECORDNUM_T *r_recordNum, 1945c51f124SMoriah Waterland int a_fd, char *a_object, char *a_key); 1955c51f124SMoriah Waterland static int _decrementLockCount(int a_fd, LOCK_T *a_theLock); 1965c51f124SMoriah Waterland static int _addLock(char *r_key, int a_fd, char *a_object, 1975c51f124SMoriah Waterland int a_exclusive, pid_t a_pid, zoneid_t a_zid); 1985c51f124SMoriah Waterland static int _incrementLockCount(int a_fd, LOCK_T *a_theLock); 1995c51f124SMoriah Waterland static FINDLOCK_T _lock_acquire(LOCK_T *a_lock, int a_fd, char *a_key, 2005c51f124SMoriah Waterland char *a_object, int a_quiet, int a_exclusive, 2015c51f124SMoriah Waterland pid_t a_pid, zoneid_t a_zid); 2025c51f124SMoriah Waterland static char *_getUniqueId(void); 2035c51f124SMoriah Waterland static int _openLockFile(char *a_root); 2045c51f124SMoriah Waterland static void sighup_handler(int a_signo); 2055c51f124SMoriah Waterland static void sigint_handler(int a_signo); 2065c51f124SMoriah Waterland static boolean_t _validateLock(int a_fd, LOCK_T *a_theLock, int a_quiet); 2075c51f124SMoriah Waterland 2085c51f124SMoriah Waterland static int signal_received = 0; 2095c51f124SMoriah Waterland 2105c51f124SMoriah Waterland /* 2115c51f124SMoriah Waterland * main methods with external entry points 2125c51f124SMoriah Waterland */ 2135c51f124SMoriah Waterland 2145c51f124SMoriah Waterland /* 2155c51f124SMoriah Waterland * Name: admin_lock 2165c51f124SMoriah Waterland * Synopsis: main entry point for pkgadm "lock" subcommand 2175c51f124SMoriah Waterland * Description: Control zone/package administrative locking 2185c51f124SMoriah Waterland * Returns: 0 on success, non-zero otherwise. 2195c51f124SMoriah Waterland */ 2205c51f124SMoriah Waterland 2215c51f124SMoriah Waterland int 2225c51f124SMoriah Waterland admin_lock(int argc, char **argv) 2235c51f124SMoriah Waterland { 2245c51f124SMoriah Waterland FINDLOCK_T tResult; 2255c51f124SMoriah Waterland LOCK_T theLock; 2265c51f124SMoriah Waterland char *RFlag = "/"; /* altRoot */ 2275c51f124SMoriah Waterland char *endptr; 2285c51f124SMoriah Waterland char *kFlag = ""; /* key */ 2295c51f124SMoriah Waterland char *oFlag = ""; /* object */ 2305c51f124SMoriah Waterland char *p; 2315c51f124SMoriah Waterland char c; 2325c51f124SMoriah Waterland int aFlag = 0; /* acquire lock */ 2335c51f124SMoriah Waterland int eFlag = 0; /* exclusive lock */ 2345c51f124SMoriah Waterland int exclusive = 1; /* exclusive vs shared lock */ 2355c51f124SMoriah Waterland int fd; 2365c51f124SMoriah Waterland int qFlag = 0; /* quiet */ 2375c51f124SMoriah Waterland int rFlag = 0; /* release lock */ 2385c51f124SMoriah Waterland int result; 2395c51f124SMoriah Waterland int sFlag = 0; /* shared lock */ 2405c51f124SMoriah Waterland int tFlag = 0; /* test comparison */ 2415c51f124SMoriah Waterland int wFlag = 0; /* wait */ 2425c51f124SMoriah Waterland long WFlag = 0; /* wait timeout */ 2435c51f124SMoriah Waterland pid_t pFlag = 0; /* process # */ 2445c51f124SMoriah Waterland struct sigaction nact; 2455c51f124SMoriah Waterland struct sigaction oact; 2465c51f124SMoriah Waterland zoneid_t zFlag = -1; /* zone i.d. */ 2475c51f124SMoriah Waterland 2485c51f124SMoriah Waterland while ((c = getopt(argc, argv, ":aek:o:p:qrR:stwW:z:")) != EOF) { 2495c51f124SMoriah Waterland switch (c) { 2505c51f124SMoriah Waterland case 'a': /* acquire lock */ 2515c51f124SMoriah Waterland aFlag++; 2525c51f124SMoriah Waterland break; 2535c51f124SMoriah Waterland 2545c51f124SMoriah Waterland case 'e': /* exclusive lock */ 2555c51f124SMoriah Waterland eFlag++; 2565c51f124SMoriah Waterland break; 2575c51f124SMoriah Waterland 2585c51f124SMoriah Waterland case 'k': /* lock-key */ 2595c51f124SMoriah Waterland kFlag = optarg; 2605c51f124SMoriah Waterland if (strlen(optarg) > LOCK_KEY_MAXLEN) { 2615c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, 262708dafbfSAlexander Pyhalov MSG_LOCK_kARG_TOOLONG, 263708dafbfSAlexander Pyhalov strlen(optarg), LOCK_KEY_MAXLEN); 2645c51f124SMoriah Waterland return (1); 2655c51f124SMoriah Waterland } 2665c51f124SMoriah Waterland break; 2675c51f124SMoriah Waterland 2685c51f124SMoriah Waterland case 'o': /* object */ 2695c51f124SMoriah Waterland oFlag = optarg; 2705c51f124SMoriah Waterland if (strlen(optarg) > LOCK_OBJECT_MAXLEN) { 2715c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, 272708dafbfSAlexander Pyhalov MSG_LOCK_oARG_TOOLONG, 273708dafbfSAlexander Pyhalov strlen(optarg), LOCK_OBJECT_MAXLEN); 2745c51f124SMoriah Waterland return (1); 2755c51f124SMoriah Waterland } 2765c51f124SMoriah Waterland break; 2775c51f124SMoriah Waterland 2785c51f124SMoriah Waterland case 'p': /* process i.d. */ 2795c51f124SMoriah Waterland errno = 0; 2805c51f124SMoriah Waterland endptr = 0; 2815c51f124SMoriah Waterland pFlag = strtol(optarg, &endptr, 10); 2825c51f124SMoriah Waterland if ((endptr != (char *)NULL) && (*endptr != '\0')) { 2835c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_pFLAG_BADINT, 284708dafbfSAlexander Pyhalov optarg, *endptr); 2855c51f124SMoriah Waterland return (1); 2865c51f124SMoriah Waterland } 2875c51f124SMoriah Waterland if ((pFlag == 0) && (errno != 0)) { 2885c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, 289708dafbfSAlexander Pyhalov MSG_LOCK_pFLAG_ERROR, 290708dafbfSAlexander Pyhalov optarg, strerror(errno)); 2915c51f124SMoriah Waterland return (1); 2925c51f124SMoriah Waterland } 2935c51f124SMoriah Waterland break; 2945c51f124SMoriah Waterland 2955c51f124SMoriah Waterland case 'q': /* quiet */ 2965c51f124SMoriah Waterland qFlag++; 2975c51f124SMoriah Waterland break; 2985c51f124SMoriah Waterland 2995c51f124SMoriah Waterland case 'r': /* release lock */ 3005c51f124SMoriah Waterland rFlag++; 3015c51f124SMoriah Waterland break; 3025c51f124SMoriah Waterland 3035c51f124SMoriah Waterland case 'R': /* alternative root */ 3045c51f124SMoriah Waterland /* if root directory is not absolute path, error */ 3055c51f124SMoriah Waterland if (*optarg != '/') { 3065c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, 307708dafbfSAlexander Pyhalov MSG_LOCK_RARG_NOT_ABSOLUTE, optarg); 3085c51f124SMoriah Waterland return (1); 3095c51f124SMoriah Waterland } 3105c51f124SMoriah Waterland 3115c51f124SMoriah Waterland /* if root directory does not exist, create it */ 3125c51f124SMoriah Waterland if (access(optarg, F_OK) != 0) { 3135c51f124SMoriah Waterland 3145c51f124SMoriah Waterland /* create top level root directory */ 3155c51f124SMoriah Waterland if (mkdirp(optarg, 0755) != 0) { 3165c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, 317708dafbfSAlexander Pyhalov MSG_LOCK_ALTROOT_CANTCREATE, 318708dafbfSAlexander Pyhalov optarg, strerror(errno)); 3195c51f124SMoriah Waterland return (1); 3205c51f124SMoriah Waterland } 3215c51f124SMoriah Waterland } 3225c51f124SMoriah Waterland 3235c51f124SMoriah Waterland /* if $ALTROOT/tmp directory does not exist create it */ 3245c51f124SMoriah Waterland p = pkgstrPrintf("%s/tmp", optarg); 3255c51f124SMoriah Waterland if (access(p, F_OK) != 0) { 3265c51f124SMoriah Waterland 3275c51f124SMoriah Waterland /* create $ALTROOT/tmp directory */ 3285c51f124SMoriah Waterland if (mkdirp(p, 0777) != 0) { 3295c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, 330708dafbfSAlexander Pyhalov MSG_LOCK_ALTROOT_CANTCREATE, 331708dafbfSAlexander Pyhalov p, strerror(errno)); 3325c51f124SMoriah Waterland return (1); 3335c51f124SMoriah Waterland } 3345c51f124SMoriah Waterland } 3355c51f124SMoriah Waterland 3365c51f124SMoriah Waterland /* if $ALTROOT/tmp directory cannot be created, exit */ 3375c51f124SMoriah Waterland if (access(p, F_OK) != 0) { 3385c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_ALTROOT_NONEXIST, 339708dafbfSAlexander Pyhalov optarg, strerror(errno)); 3405c51f124SMoriah Waterland return (1); 3415c51f124SMoriah Waterland } 3425c51f124SMoriah Waterland 3435c51f124SMoriah Waterland (void) free(p); 3445c51f124SMoriah Waterland 3455c51f124SMoriah Waterland RFlag = optarg; 3465c51f124SMoriah Waterland break; 3475c51f124SMoriah Waterland 3485c51f124SMoriah Waterland case 's': /* shared */ 3495c51f124SMoriah Waterland sFlag++; 3505c51f124SMoriah Waterland break; 3515c51f124SMoriah Waterland 3525c51f124SMoriah Waterland case 't': /* test comparison */ 3535c51f124SMoriah Waterland tFlag++; 3545c51f124SMoriah Waterland break; 3555c51f124SMoriah Waterland 3565c51f124SMoriah Waterland case 'w': /* wait */ 3575c51f124SMoriah Waterland wFlag++; 3585c51f124SMoriah Waterland break; 3595c51f124SMoriah Waterland 3605c51f124SMoriah Waterland case 'W': /* wait with timeout */ 3615c51f124SMoriah Waterland errno = 0; 3625c51f124SMoriah Waterland endptr = 0; 3635c51f124SMoriah Waterland WFlag = strtol(optarg, &endptr, 10); 3645c51f124SMoriah Waterland if ((endptr != (char *)NULL) && (*endptr != '\0')) { 3655c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_WFLAG_BADINT, 366708dafbfSAlexander Pyhalov optarg, *endptr); 3675c51f124SMoriah Waterland return (1); 3685c51f124SMoriah Waterland } 3695c51f124SMoriah Waterland if ((WFlag == 0) && (errno != 0)) { 3705c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, 371708dafbfSAlexander Pyhalov MSG_LOCK_WFLAG_ERROR, 372708dafbfSAlexander Pyhalov optarg, strerror(errno)); 3735c51f124SMoriah Waterland return (1); 3745c51f124SMoriah Waterland } 3755c51f124SMoriah Waterland wFlag++; 3765c51f124SMoriah Waterland break; 3775c51f124SMoriah Waterland 3785c51f124SMoriah Waterland case 'z': /* zone i.d. */ 3795c51f124SMoriah Waterland errno = 0; 3805c51f124SMoriah Waterland endptr = 0; 3815c51f124SMoriah Waterland zFlag = strtol(optarg, &endptr, 10); 3825c51f124SMoriah Waterland if ((endptr != (char *)NULL) && (*endptr != '\0')) { 3835c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_zFLAG_BADINT, 384708dafbfSAlexander Pyhalov optarg, *endptr); 3855c51f124SMoriah Waterland return (1); 3865c51f124SMoriah Waterland } 3875c51f124SMoriah Waterland if ((zFlag == 0) && (errno != 0)) { 3885c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, 389708dafbfSAlexander Pyhalov MSG_LOCK_zFLAG_ERROR, 390708dafbfSAlexander Pyhalov optarg, strerror(errno)); 3915c51f124SMoriah Waterland return (1); 3925c51f124SMoriah Waterland } 3935c51f124SMoriah Waterland break; 3945c51f124SMoriah Waterland 3955c51f124SMoriah Waterland case ':': 3965c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_MISSING_OPERAND, optopt); 397*26ec61e2SToomas Soome /* FALLTHROUGH */ 3985c51f124SMoriah Waterland case '?': 3995c51f124SMoriah Waterland 4005c51f124SMoriah Waterland default: 4015c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_USAGE); 4025c51f124SMoriah Waterland return (1); 4035c51f124SMoriah Waterland } 4045c51f124SMoriah Waterland } 4055c51f124SMoriah Waterland 4065c51f124SMoriah Waterland /* 4075c51f124SMoriah Waterland * validate arguments 4085c51f124SMoriah Waterland */ 4095c51f124SMoriah Waterland 4105c51f124SMoriah Waterland /* if -t option is specified, override all other options */ 4115c51f124SMoriah Waterland 4125c51f124SMoriah Waterland if (tFlag) { 4135c51f124SMoriah Waterland int rs; 4145c51f124SMoriah Waterland int rx; 4155c51f124SMoriah Waterland int a; 4165c51f124SMoriah Waterland 4175c51f124SMoriah Waterland /* only 2 or 3 args are valid */ 4185c51f124SMoriah Waterland 4195c51f124SMoriah Waterland a = argc-optind; 4205c51f124SMoriah Waterland if ((a < 2) || (a > 3)) { 4215c51f124SMoriah Waterland (void) fprintf(stderr, MSG_T_OPTION_ARGS, argc-optind); 4225c51f124SMoriah Waterland return (1); 4235c51f124SMoriah Waterland } 4245c51f124SMoriah Waterland 4255c51f124SMoriah Waterland /* if 3rd argument given, it is return value to check */ 4265c51f124SMoriah Waterland 4275c51f124SMoriah Waterland if (a == 3) { 4285c51f124SMoriah Waterland rs = atoi(argv[optind+2]); 4295c51f124SMoriah Waterland } 4305c51f124SMoriah Waterland rx = _lockMatch(argv[optind+0], argv[optind+1]); 4315c51f124SMoriah Waterland 4325c51f124SMoriah Waterland /* if 3rd argument not given, code to check is code returned */ 4335c51f124SMoriah Waterland 4345c51f124SMoriah Waterland if (a == 2) { 4355c51f124SMoriah Waterland rs = rx; 4365c51f124SMoriah Waterland } 4375c51f124SMoriah Waterland 4385c51f124SMoriah Waterland /* report results */ 4395c51f124SMoriah Waterland 4405c51f124SMoriah Waterland if (a == 2) { 4415c51f124SMoriah Waterland (void) fprintf(stderr, MSG_T_RESULT_TWO, 442708dafbfSAlexander Pyhalov rx, argv[optind+0], argv[optind+1]); 4435c51f124SMoriah Waterland return (rx); 4445c51f124SMoriah Waterland } 4455c51f124SMoriah Waterland 4465c51f124SMoriah Waterland if (rx != rs) { 4475c51f124SMoriah Waterland (void) fprintf(stderr, MSG_T_RESULT_THREE, 448708dafbfSAlexander Pyhalov rs, rx, argv[optind+0], argv[optind+1]); 4495c51f124SMoriah Waterland } 4505c51f124SMoriah Waterland 4515c51f124SMoriah Waterland /* always successful */ 4525c51f124SMoriah Waterland 4535c51f124SMoriah Waterland return (rx == rs ? 0 : 1); 4545c51f124SMoriah Waterland } 4555c51f124SMoriah Waterland 4565c51f124SMoriah Waterland /* must be no non-option arguments left */ 4575c51f124SMoriah Waterland 4585c51f124SMoriah Waterland if ((argc-optind) > 0) { 4595c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_USAGE); 4605c51f124SMoriah Waterland return (1); 4615c51f124SMoriah Waterland } 4625c51f124SMoriah Waterland 4635c51f124SMoriah Waterland /* -a and -r cannot be used together */ 4645c51f124SMoriah Waterland 4655c51f124SMoriah Waterland if (aFlag && rFlag) { 4665c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_ar_TOGETHER); 4675c51f124SMoriah Waterland return (1); 4685c51f124SMoriah Waterland } 4695c51f124SMoriah Waterland 4705c51f124SMoriah Waterland /* -e and -s cannot be used together */ 4715c51f124SMoriah Waterland 4725c51f124SMoriah Waterland if (eFlag && sFlag) { 4735c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_es_TOGETHER); 4745c51f124SMoriah Waterland return (1); 4755c51f124SMoriah Waterland } 4765c51f124SMoriah Waterland 4775c51f124SMoriah Waterland /* -e can only be used if -a is used */ 4785c51f124SMoriah Waterland 4795c51f124SMoriah Waterland if (!aFlag && eFlag) { 4805c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_e_without_a); 4815c51f124SMoriah Waterland return (1); 4825c51f124SMoriah Waterland } 4835c51f124SMoriah Waterland 4845c51f124SMoriah Waterland /* -s can only be used if -a is used */ 4855c51f124SMoriah Waterland 4865c51f124SMoriah Waterland if (!aFlag && sFlag) { 4875c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_s_without_a); 4885c51f124SMoriah Waterland return (1); 4895c51f124SMoriah Waterland } 4905c51f124SMoriah Waterland 4915c51f124SMoriah Waterland /* 4925c51f124SMoriah Waterland * perform the requested operation 4935c51f124SMoriah Waterland */ 4945c51f124SMoriah Waterland 4955c51f124SMoriah Waterland /* 4965c51f124SMoriah Waterland * hook SIGINT and SIGHUP interrupts into quit.c's trap handler 4975c51f124SMoriah Waterland */ 4985c51f124SMoriah Waterland 4995c51f124SMoriah Waterland /* hold SIGINT/SIGHUP interrupts */ 5005c51f124SMoriah Waterland 5015c51f124SMoriah Waterland (void) sighold(SIGHUP); 5025c51f124SMoriah Waterland (void) sighold(SIGINT); 5035c51f124SMoriah Waterland 5045c51f124SMoriah Waterland /* connect sigint_handler() to SIGINT */ 5055c51f124SMoriah Waterland 5065c51f124SMoriah Waterland nact.sa_handler = sigint_handler; 5075c51f124SMoriah Waterland nact.sa_flags = SA_RESTART; 5085c51f124SMoriah Waterland (void) sigemptyset(&nact.sa_mask); 5095c51f124SMoriah Waterland 5104f39e64dSToomas Soome (void) sigaction(SIGINT, &nact, &oact); 5115c51f124SMoriah Waterland 5124f39e64dSToomas Soome /* connect sighup_handler() to SIGHUP */ 5135c51f124SMoriah Waterland 5145c51f124SMoriah Waterland nact.sa_handler = sighup_handler; 5155c51f124SMoriah Waterland nact.sa_flags = SA_RESTART; 5165c51f124SMoriah Waterland (void) sigemptyset(&nact.sa_mask); 5175c51f124SMoriah Waterland 5184f39e64dSToomas Soome (void) sigaction(SIGHUP, &nact, &oact); 5195c51f124SMoriah Waterland 5205c51f124SMoriah Waterland /* release hold on signals */ 5215c51f124SMoriah Waterland 5225c51f124SMoriah Waterland (void) sigrelse(SIGHUP); 5235c51f124SMoriah Waterland (void) sigrelse(SIGINT); 5245c51f124SMoriah Waterland 5255c51f124SMoriah Waterland /* open the lock file */ 5265c51f124SMoriah Waterland 5275c51f124SMoriah Waterland fd = _openLockFile(RFlag); 5285c51f124SMoriah Waterland if (fd < 0) { 5295c51f124SMoriah Waterland return (1); 5305c51f124SMoriah Waterland } 5315c51f124SMoriah Waterland 5325c51f124SMoriah Waterland if (aFlag) { 5335c51f124SMoriah Waterland /* set "exclusive" mode based on -e/-s flag used */ 5345c51f124SMoriah Waterland 5355c51f124SMoriah Waterland if (sFlag) { 5365c51f124SMoriah Waterland exclusive = 0; 5375c51f124SMoriah Waterland } else if (eFlag) { 5385c51f124SMoriah Waterland exclusive = 1; 5395c51f124SMoriah Waterland } 5405c51f124SMoriah Waterland 5415c51f124SMoriah Waterland /* acquire lock */ 5425c51f124SMoriah Waterland 5435c51f124SMoriah Waterland tResult = lock_acquire(&theLock, &fd, RFlag, kFlag, oFlag, 544708dafbfSAlexander Pyhalov qFlag, wFlag, WFlag, exclusive, RFlag, pFlag, zFlag); 5455c51f124SMoriah Waterland 5465c51f124SMoriah Waterland switch (tResult) { 5475c51f124SMoriah Waterland case FINDLOCK_LOCKACQUIRED: 5485c51f124SMoriah Waterland (void) fprintf(stdout, "%s\n", 549708dafbfSAlexander Pyhalov theLock._lrLock.lockKey); 5505c51f124SMoriah Waterland result = 0; 5515c51f124SMoriah Waterland break; 5525c51f124SMoriah Waterland case FINDLOCK_LOCKED: 5535c51f124SMoriah Waterland (void) fprintf(stdout, "%s\n", 554708dafbfSAlexander Pyhalov theLock._lrLock.lockObject); 5555c51f124SMoriah Waterland result = 1; 5565c51f124SMoriah Waterland break; 5575c51f124SMoriah Waterland default: 5585c51f124SMoriah Waterland result = 1; 5595c51f124SMoriah Waterland break; 5605c51f124SMoriah Waterland } 5615c51f124SMoriah Waterland 5625c51f124SMoriah Waterland } else if (rFlag) { 5635c51f124SMoriah Waterland /* release lock */ 5645c51f124SMoriah Waterland result = lock_release(fd, kFlag, oFlag, qFlag); 5655c51f124SMoriah Waterland } else { 5665c51f124SMoriah Waterland /* lock status */ 5675c51f124SMoriah Waterland result = lock_status(fd, kFlag, oFlag, qFlag); 5685c51f124SMoriah Waterland } 5695c51f124SMoriah Waterland 5705c51f124SMoriah Waterland /* close the lock file */ 5715c51f124SMoriah Waterland 5725c51f124SMoriah Waterland (void) close(fd); 5735c51f124SMoriah Waterland 5745c51f124SMoriah Waterland /* return results of operation */ 5755c51f124SMoriah Waterland 5765c51f124SMoriah Waterland return (result); 5775c51f124SMoriah Waterland } 5785c51f124SMoriah Waterland 5795c51f124SMoriah Waterland /* 5805c51f124SMoriah Waterland * local main function implementation methods 5815c51f124SMoriah Waterland */ 5825c51f124SMoriah Waterland 5835c51f124SMoriah Waterland /* 5845c51f124SMoriah Waterland * Name: lock_acquire 5855c51f124SMoriah Waterland * Description: implement lock acquisition implementing the wait/timeouts 5865c51f124SMoriah Waterland * Calls _lock_acquire to attempt lock acquisition. 5875c51f124SMoriah Waterland * Arguments: 5885c51f124SMoriah Waterland * a_theLock - lock object filled with contents of existing lock 5895c51f124SMoriah Waterland * a_fd - file descriptor opened on the lock file 5905c51f124SMoriah Waterland * a_root - root of file system to manipulate locks on 5915c51f124SMoriah Waterland * a_key - key associated with lock to acquire 5925c51f124SMoriah Waterland * a_object - object associated with lock to acquire 5935c51f124SMoriah Waterland * a_wait - wait if lock cannot be acquired flag: 5945c51f124SMoriah Waterland * == 0 - do not wait 5955c51f124SMoriah Waterland * != 0 - wait 5965c51f124SMoriah Waterland * a_timeout - timeout if waiting to acquire busy lock: 5975c51f124SMoriah Waterland * == 0 - no timeout (wait forever) 5985c51f124SMoriah Waterland * != 0 - max # seconds to wait to acquire busy lock 5995c51f124SMoriah Waterland * a_quiet - quiet mode enabled flag 6005c51f124SMoriah Waterland * a_exclusive - exclusive/shared lock flag 6015c51f124SMoriah Waterland * a_pid - if != 0 process i.d. to associate with this lock 6025c51f124SMoriah Waterland * a_zid - if >= 0 - zone i.d. to associate with this lock 6035c51f124SMoriah Waterland * Returns: int 6045c51f124SMoriah Waterland * == 0 - successful 6055c51f124SMoriah Waterland * != 0 - not successful 6065c51f124SMoriah Waterland */ 6075c51f124SMoriah Waterland 6085c51f124SMoriah Waterland static FINDLOCK_T 6095c51f124SMoriah Waterland lock_acquire(LOCK_T *a_theLock, int *a_fd, char *a_root, char *a_key, 610708dafbfSAlexander Pyhalov char *a_object, int a_quiet, int a_wait, long a_timeout, 611708dafbfSAlexander Pyhalov int a_exclusive, char *a_altRoot, pid_t a_pid, zoneid_t a_zid) 6125c51f124SMoriah Waterland { 6135c51f124SMoriah Waterland int notified = 0; 6145c51f124SMoriah Waterland FINDLOCK_T result; 6155c51f124SMoriah Waterland time_t timeout; 6165c51f124SMoriah Waterland int closeOnExit = 0; 6175c51f124SMoriah Waterland 6185c51f124SMoriah Waterland /* reset the lock */ 6195c51f124SMoriah Waterland 6205c51f124SMoriah Waterland bzero(a_theLock, sizeof (LOCK_T)); 6215c51f124SMoriah Waterland 6225c51f124SMoriah Waterland /* open file if not open */ 6235c51f124SMoriah Waterland 6245c51f124SMoriah Waterland if ((*a_fd) < 0) { 6255c51f124SMoriah Waterland (*a_fd) = _openLockFile(a_altRoot); 6265c51f124SMoriah Waterland if ((*a_fd) < 0) { 6275c51f124SMoriah Waterland return (FINDLOCK_ERROR); 6285c51f124SMoriah Waterland } 6295c51f124SMoriah Waterland closeOnExit++; 6305c51f124SMoriah Waterland } 6315c51f124SMoriah Waterland 6325c51f124SMoriah Waterland /* compute time after which acquire times out */ 6335c51f124SMoriah Waterland 6345c51f124SMoriah Waterland timeout = time((time_t *)NULL) + a_timeout; 6355c51f124SMoriah Waterland 6365c51f124SMoriah Waterland for (;;) { 6375c51f124SMoriah Waterland time_t curtime; 6385c51f124SMoriah Waterland 6395c51f124SMoriah Waterland /* attempt to aquire the lock */ 6405c51f124SMoriah Waterland 6415c51f124SMoriah Waterland result = _lock_acquire(a_theLock, *a_fd, a_key, a_object, 642708dafbfSAlexander Pyhalov a_quiet, a_exclusive, a_pid, a_zid); 6435c51f124SMoriah Waterland 6445c51f124SMoriah Waterland /* return result if any result other than object is locked */ 6455c51f124SMoriah Waterland 6465c51f124SMoriah Waterland switch (result) { 6475c51f124SMoriah Waterland case FINDLOCK_LOCKACQUIRED: 6485c51f124SMoriah Waterland 6495c51f124SMoriah Waterland /* close lock file if opened in this function */ 6505c51f124SMoriah Waterland 6515c51f124SMoriah Waterland if (closeOnExit) { 6525c51f124SMoriah Waterland (void) close(*a_fd); 6535c51f124SMoriah Waterland *a_fd = -1; 6545c51f124SMoriah Waterland } 6555c51f124SMoriah Waterland 6565c51f124SMoriah Waterland return (FINDLOCK_LOCKACQUIRED); 6575c51f124SMoriah Waterland 6585c51f124SMoriah Waterland case FINDLOCK_FOUND: 6595c51f124SMoriah Waterland case FINDLOCK_NOTFOUND: 6605c51f124SMoriah Waterland case FINDLOCK_KEYMISMATCH: 6615c51f124SMoriah Waterland case FINDLOCK_NOTLOCKED: 6625c51f124SMoriah Waterland case FINDLOCK_ERROR: 6635c51f124SMoriah Waterland default: 6645c51f124SMoriah Waterland /* close lock file if opened in this function */ 6655c51f124SMoriah Waterland 6665c51f124SMoriah Waterland if (closeOnExit) { 6675c51f124SMoriah Waterland (void) close(*a_fd); 6685c51f124SMoriah Waterland *a_fd = -1; 6695c51f124SMoriah Waterland } 6705c51f124SMoriah Waterland 6715c51f124SMoriah Waterland return (result); 6725c51f124SMoriah Waterland 6735c51f124SMoriah Waterland case FINDLOCK_LOCKED: 6745c51f124SMoriah Waterland ; 6755c51f124SMoriah Waterland /* FALLTHROUGH */ 6765c51f124SMoriah Waterland } 6775c51f124SMoriah Waterland 6785c51f124SMoriah Waterland /* 6795c51f124SMoriah Waterland * object locked OR SIGINT/SIGHUP interrupt received; 6805c51f124SMoriah Waterland * return error if not waiting for lock OR signal received 6815c51f124SMoriah Waterland */ 6825c51f124SMoriah Waterland 6835c51f124SMoriah Waterland if ((a_wait == 0) || (signal_received != 0)) { 6845c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR, 685708dafbfSAlexander Pyhalov MSG_LOCK_ACQUIRE_BUSY_FIRST, 686708dafbfSAlexander Pyhalov a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR, 687708dafbfSAlexander Pyhalov a_object, a_key, 688708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockObject, 689708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 690708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 691708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive != 692708dafbfSAlexander Pyhalov a_exclusive ? "" : 693708dafbfSAlexander Pyhalov MSG_LOCK_ACQUIRE_BUSY_ADDITIONAL); 6945c51f124SMoriah Waterland 6955c51f124SMoriah Waterland /* close lock file if opened in this function */ 6965c51f124SMoriah Waterland 6975c51f124SMoriah Waterland if (closeOnExit) { 6985c51f124SMoriah Waterland (void) close(*a_fd); 6995c51f124SMoriah Waterland *a_fd = -1; 7005c51f124SMoriah Waterland } 7015c51f124SMoriah Waterland 7025c51f124SMoriah Waterland return (FINDLOCK_LOCKED); 7035c51f124SMoriah Waterland } 7045c51f124SMoriah Waterland 7055c51f124SMoriah Waterland /* waiting for lock - if timeout specified see if time left */ 7065c51f124SMoriah Waterland 7075c51f124SMoriah Waterland if (a_timeout > 0) { 7085c51f124SMoriah Waterland curtime = time((time_t *)NULL); 7095c51f124SMoriah Waterland if (curtime > timeout) { 7105c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR, 711708dafbfSAlexander Pyhalov MSG_LOCK_ACQUIRE_TIMEDOUT, 712708dafbfSAlexander Pyhalov a_exclusive ? 713708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 714708dafbfSAlexander Pyhalov a_object, a_key); 7155c51f124SMoriah Waterland 7165c51f124SMoriah Waterland /* close lock file if opened in this function */ 7175c51f124SMoriah Waterland 7185c51f124SMoriah Waterland if (closeOnExit) { 7195c51f124SMoriah Waterland (void) close(*a_fd); 7205c51f124SMoriah Waterland *a_fd = -1; 7215c51f124SMoriah Waterland } 7225c51f124SMoriah Waterland 7235c51f124SMoriah Waterland return (FINDLOCK_ERROR); 7245c51f124SMoriah Waterland } 7255c51f124SMoriah Waterland } 7265c51f124SMoriah Waterland 7275c51f124SMoriah Waterland /* 7285c51f124SMoriah Waterland * waiting to aquire lock: 7295c51f124SMoriah Waterland * - notify waiting (one time only) 7305c51f124SMoriah Waterland * - close lock file 7315c51f124SMoriah Waterland * - sleep 7325c51f124SMoriah Waterland * - open lock file 7335c51f124SMoriah Waterland * - try again 7345c51f124SMoriah Waterland */ 7355c51f124SMoriah Waterland 7365c51f124SMoriah Waterland /* notify once */ 7375c51f124SMoriah Waterland 7385c51f124SMoriah Waterland if (notified++ == 0) { 7395c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_WRN, 740708dafbfSAlexander Pyhalov MSG_LOCK_ACQUIRE_WAITING, 741708dafbfSAlexander Pyhalov a_object); 7425c51f124SMoriah Waterland } 7435c51f124SMoriah Waterland 7445c51f124SMoriah Waterland /* close lock file */ 7455c51f124SMoriah Waterland 7465c51f124SMoriah Waterland (void) close(*a_fd); 7475c51f124SMoriah Waterland 7485c51f124SMoriah Waterland /* wait (sleep) */ 7495c51f124SMoriah Waterland 7505c51f124SMoriah Waterland (void) sleep(LOCK_SLEEP_INTERVAL); 7515c51f124SMoriah Waterland 7525c51f124SMoriah Waterland /* open the lock file and try again */ 7535c51f124SMoriah Waterland 7545c51f124SMoriah Waterland *a_fd = _openLockFile(a_root); 7555c51f124SMoriah Waterland if (*a_fd < 0) { 7565c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_ACQUIRE_REOPEN_FAILED, 757708dafbfSAlexander Pyhalov a_object); 7585c51f124SMoriah Waterland 7595c51f124SMoriah Waterland /* close lock file if opened in this function */ 7605c51f124SMoriah Waterland 7615c51f124SMoriah Waterland if (closeOnExit) { 7625c51f124SMoriah Waterland (void) close(*a_fd); 7635c51f124SMoriah Waterland *a_fd = -1; 7645c51f124SMoriah Waterland } 7655c51f124SMoriah Waterland 7665c51f124SMoriah Waterland return (FINDLOCK_ERROR); 7675c51f124SMoriah Waterland } 7685c51f124SMoriah Waterland } 7695c51f124SMoriah Waterland } 7705c51f124SMoriah Waterland 7715c51f124SMoriah Waterland /* 7725c51f124SMoriah Waterland * Name: lock_release 7735c51f124SMoriah Waterland * Description: implement lock release 7745c51f124SMoriah Waterland * Arguments: 7755c51f124SMoriah Waterland * a_fd - file descriptor opened on the lock file 7765c51f124SMoriah Waterland * a_key - key associated with lock to release 7775c51f124SMoriah Waterland * a_object - object associated with lock to release 7785c51f124SMoriah Waterland * a_quiet - quiet mode enabled flag 7795c51f124SMoriah Waterland * Returns: int 7805c51f124SMoriah Waterland * == 0 - successful 7815c51f124SMoriah Waterland * != 0 - not successful 7825c51f124SMoriah Waterland */ 7835c51f124SMoriah Waterland 7845c51f124SMoriah Waterland static int 7855c51f124SMoriah Waterland lock_release(int a_fd, char *a_key, char *a_object, int a_quiet) 7865c51f124SMoriah Waterland { 7875c51f124SMoriah Waterland RECORDNUM_T recordNum; 7885c51f124SMoriah Waterland LOCK_T theLock; 7895c51f124SMoriah Waterland FINDLOCK_T result; 7905c51f124SMoriah Waterland 7915c51f124SMoriah Waterland /* entry debugging info */ 7925c51f124SMoriah Waterland 7935c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_RELEASE_ENTRY, 794708dafbfSAlexander Pyhalov a_key, a_object, a_quiet); 7955c51f124SMoriah Waterland 7965c51f124SMoriah Waterland /* find the lock to be released */ 7975c51f124SMoriah Waterland 7985c51f124SMoriah Waterland result = _findLock(&theLock, &recordNum, a_fd, a_object, a_key); 7995c51f124SMoriah Waterland 8005c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_RELEASE_FINDRESULT, 801708dafbfSAlexander Pyhalov result, recordNum); 8025c51f124SMoriah Waterland 8035c51f124SMoriah Waterland /* determine how to release the lock if found */ 8045c51f124SMoriah Waterland 8055c51f124SMoriah Waterland switch (result) { 8065c51f124SMoriah Waterland /* 8075c51f124SMoriah Waterland * object is not locked but a key was specified 8085c51f124SMoriah Waterland */ 8095c51f124SMoriah Waterland case FINDLOCK_NOTLOCKED: 8105c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR, 811708dafbfSAlexander Pyhalov MSG_LOCK_RELEASE_NOTLOCKED, 812708dafbfSAlexander Pyhalov a_object, a_key); 8135c51f124SMoriah Waterland return (result); 8145c51f124SMoriah Waterland 8155c51f124SMoriah Waterland /* 8165c51f124SMoriah Waterland * object is locked and no matching key was specified 8175c51f124SMoriah Waterland */ 8185c51f124SMoriah Waterland case FINDLOCK_LOCKED: 8195c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR, 820708dafbfSAlexander Pyhalov MSG_LOCK_RELEASE_LOCKED, 821708dafbfSAlexander Pyhalov a_object, a_key); 8225c51f124SMoriah Waterland return (result); 8235c51f124SMoriah Waterland 8245c51f124SMoriah Waterland /* 8255c51f124SMoriah Waterland * object is not locked 8265c51f124SMoriah Waterland */ 8275c51f124SMoriah Waterland case FINDLOCK_NOTFOUND: 8285c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR, 829708dafbfSAlexander Pyhalov MSG_LOCK_RELEASE_NOTFOUND, 830708dafbfSAlexander Pyhalov a_object, a_key); 8315c51f124SMoriah Waterland return (result); 8325c51f124SMoriah Waterland 8335c51f124SMoriah Waterland /* 8345c51f124SMoriah Waterland * object is locked and specified key does not match 8355c51f124SMoriah Waterland */ 8365c51f124SMoriah Waterland case FINDLOCK_KEYMISMATCH: 8375c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR, 838708dafbfSAlexander Pyhalov MSG_LOCK_RELEASE_KEYMISMATCH, 839708dafbfSAlexander Pyhalov a_object); 8405c51f124SMoriah Waterland return (result); 8415c51f124SMoriah Waterland 8425c51f124SMoriah Waterland /* 8435c51f124SMoriah Waterland * error determining if object is locked 8445c51f124SMoriah Waterland */ 8455c51f124SMoriah Waterland case FINDLOCK_ERROR: 8465c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR, 847708dafbfSAlexander Pyhalov MSG_LOCK_RELEASE_ERROR, 848708dafbfSAlexander Pyhalov a_object, a_key); 8495c51f124SMoriah Waterland perror(LOCK_FILENAME); 8505c51f124SMoriah Waterland return (result); 8515c51f124SMoriah Waterland 8525c51f124SMoriah Waterland /* 8535c51f124SMoriah Waterland * object is locked and specified key matches 8545c51f124SMoriah Waterland */ 8555c51f124SMoriah Waterland case FINDLOCK_FOUND: 8565c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_RELEASE_FOUND, 857708dafbfSAlexander Pyhalov a_object, a_key); 8585c51f124SMoriah Waterland (void) _decrementLockCount(a_fd, &theLock); 8595c51f124SMoriah Waterland break; 8605c51f124SMoriah Waterland 8615c51f124SMoriah Waterland /* 8625c51f124SMoriah Waterland * unknown return 8635c51f124SMoriah Waterland */ 8645c51f124SMoriah Waterland default: 8655c51f124SMoriah Waterland result = FINDLOCK_ERROR; 8665c51f124SMoriah Waterland break; 8675c51f124SMoriah Waterland 8685c51f124SMoriah Waterland } 8695c51f124SMoriah Waterland return (result); 8705c51f124SMoriah Waterland } 8715c51f124SMoriah Waterland 8725c51f124SMoriah Waterland /* 8735c51f124SMoriah Waterland * Name: lock_status 8745c51f124SMoriah Waterland * Description: implement lock status display/inquiry 8755c51f124SMoriah Waterland * Arguments: 8765c51f124SMoriah Waterland * a_fd - file descriptor opened on the lock file 8775c51f124SMoriah Waterland * a_key - key associated with lock to look up 8785c51f124SMoriah Waterland * a_object - object associated with lock to look up 8795c51f124SMoriah Waterland * a_quiet - quiet mode enabled flag 8805c51f124SMoriah Waterland * Returns: int 8815c51f124SMoriah Waterland * == 0 - successful 8825c51f124SMoriah Waterland * != 0 - not successful 8835c51f124SMoriah Waterland */ 8845c51f124SMoriah Waterland 8855c51f124SMoriah Waterland static int 8865c51f124SMoriah Waterland lock_status(int a_fd, char *a_key, char *a_object, int a_quiet) 8875c51f124SMoriah Waterland { 8885c51f124SMoriah Waterland ADMINLOCK_T *pll; 8895c51f124SMoriah Waterland LOCK_T theLock; 8905c51f124SMoriah Waterland RECORDNUM_T recordNum = 0; 8915c51f124SMoriah Waterland char *pld; 8925c51f124SMoriah Waterland int found = 0; 8935c51f124SMoriah Waterland long pls; 8945c51f124SMoriah Waterland 8955c51f124SMoriah Waterland /* entry debugging info */ 8965c51f124SMoriah Waterland 8975c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_STATUS_ENTRY, 898708dafbfSAlexander Pyhalov a_key, a_object); 8995c51f124SMoriah Waterland 9005c51f124SMoriah Waterland /* localize references to lock object */ 9015c51f124SMoriah Waterland 9025c51f124SMoriah Waterland pld = &theLock._lrLockData[0]; 9035c51f124SMoriah Waterland pll = &theLock._lrLock; 9045c51f124SMoriah Waterland pls = sizeof (theLock._lrLockData); 9055c51f124SMoriah Waterland 9065c51f124SMoriah Waterland bzero(pld, pls); 9075c51f124SMoriah Waterland 9085c51f124SMoriah Waterland /* read and process each lock */ 9095c51f124SMoriah Waterland 9105c51f124SMoriah Waterland for (; pread(a_fd, pld, pls, pls*recordNum) == pls; recordNum++) { 9115c51f124SMoriah Waterland /* debug info on this lock */ 9125c51f124SMoriah Waterland 9135c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_STATUS_READRECORD, 914708dafbfSAlexander Pyhalov recordNum, pll->lockCount, 915708dafbfSAlexander Pyhalov pll->lockObject, pll->lockKey, pll->lockPid, 916708dafbfSAlexander Pyhalov pll->lockZoneId); 9175c51f124SMoriah Waterland 9185c51f124SMoriah Waterland /* ignore if key specified and key does not match */ 9195c51f124SMoriah Waterland 9205c51f124SMoriah Waterland if ((*a_key != '\0') && 921708dafbfSAlexander Pyhalov (strcmp(pll->lockKey, a_key) != 0)) { 9225c51f124SMoriah Waterland continue; 9235c51f124SMoriah Waterland } 9245c51f124SMoriah Waterland 9255c51f124SMoriah Waterland /* ignore if object specified and object does not match */ 9265c51f124SMoriah Waterland 9275c51f124SMoriah Waterland if ((*a_object != '\0') && 928708dafbfSAlexander Pyhalov (strcmp(pll->lockObject, a_object) != 0)) { 9295c51f124SMoriah Waterland continue; 9305c51f124SMoriah Waterland } 9315c51f124SMoriah Waterland 9325c51f124SMoriah Waterland found++; 9335c51f124SMoriah Waterland 9345c51f124SMoriah Waterland /* process next lock if quiet operation */ 9355c51f124SMoriah Waterland 9365c51f124SMoriah Waterland if (a_quiet != 0) { 9375c51f124SMoriah Waterland continue; 9385c51f124SMoriah Waterland } 9395c51f124SMoriah Waterland 9405c51f124SMoriah Waterland /* output header if first lock object */ 9415c51f124SMoriah Waterland 9425c51f124SMoriah Waterland if (found == 1) { 9435c51f124SMoriah Waterland (void) fprintf(stdout, 944708dafbfSAlexander Pyhalov "%2s %2s %3s %8s %3s %9s %37s %s\n", 945708dafbfSAlexander Pyhalov "i#", "l#", "cnt", "pid", "zid", "lock-type", 946708dafbfSAlexander Pyhalov "---------------lock-key-------------", 947708dafbfSAlexander Pyhalov "lock-object"); 9485c51f124SMoriah Waterland } 9495c51f124SMoriah Waterland 9505c51f124SMoriah Waterland /* output status line for this lock object */ 9515c51f124SMoriah Waterland 9525c51f124SMoriah Waterland (void) fprintf(stdout, 953708dafbfSAlexander Pyhalov "%2ld %2ld %3ld %8ld %3d %9s %37s %s\n", 954708dafbfSAlexander Pyhalov recordNum, pll->lockRecordNum, pll->lockCount, 955708dafbfSAlexander Pyhalov pll->lockPid, pll->lockZoneId, 956708dafbfSAlexander Pyhalov pll->lockExclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR, 957708dafbfSAlexander Pyhalov pll->lockKey, 958708dafbfSAlexander Pyhalov *pll->lockObject == '\0' ? "*" : pll->lockObject); 9595c51f124SMoriah Waterland } 9605c51f124SMoriah Waterland 9615c51f124SMoriah Waterland /* return == 0 if found, != 0 if not found */ 9625c51f124SMoriah Waterland 9635c51f124SMoriah Waterland return (found == 0 ? 1 : 0); 9645c51f124SMoriah Waterland } 9655c51f124SMoriah Waterland 9665c51f124SMoriah Waterland /* 9675c51f124SMoriah Waterland * local utility functions 9685c51f124SMoriah Waterland */ 9695c51f124SMoriah Waterland 9705c51f124SMoriah Waterland /* 9715c51f124SMoriah Waterland * Name: _lock_acquire 9725c51f124SMoriah Waterland * Description: implement lock acquisition without wait/timeouts 9735c51f124SMoriah Waterland * Arguments: 9745c51f124SMoriah Waterland * a_theLock - lock object filled with contents of existing lock 9755c51f124SMoriah Waterland * a_fd - file descriptor opened on the lock file 9765c51f124SMoriah Waterland * a_key - key associated with lock to acquire 9775c51f124SMoriah Waterland * a_object - object associated with lock to acquire 9785c51f124SMoriah Waterland * a_quiet - quiet mode enabled flag 9795c51f124SMoriah Waterland * a_exclusive - exclusive/shared lock flag 9805c51f124SMoriah Waterland * a_pid - if != 0 process i.d. to associate with this lock 9815c51f124SMoriah Waterland * a_zid - if >= 0 zone i.d. to associate with this lock 9825c51f124SMoriah Waterland * Returns: FINDLOCK_T 9835c51f124SMoriah Waterland */ 9845c51f124SMoriah Waterland 9855c51f124SMoriah Waterland static FINDLOCK_T 9865c51f124SMoriah Waterland _lock_acquire(LOCK_T *a_theLock, int a_fd, char *a_key, 987708dafbfSAlexander Pyhalov char *a_object, int a_quiet, int a_exclusive, pid_t a_pid, 988708dafbfSAlexander Pyhalov zoneid_t a_zid) 9895c51f124SMoriah Waterland { 9905c51f124SMoriah Waterland RECORDNUM_T recordNum; 9915c51f124SMoriah Waterland FINDLOCK_T result; 9925c51f124SMoriah Waterland char key[LOCK_KEY_MAXLEN+1] = {'\0'}; 9935c51f124SMoriah Waterland 9945c51f124SMoriah Waterland /* entry debugging info */ 9955c51f124SMoriah Waterland 9965c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_ACQUIRE_ENTRY, 997708dafbfSAlexander Pyhalov a_key, a_object, a_quiet, a_exclusive); 9985c51f124SMoriah Waterland 9995c51f124SMoriah Waterland /* is the specified object already locked? */ 10005c51f124SMoriah Waterland 10015c51f124SMoriah Waterland for (;;) { 10025c51f124SMoriah Waterland result = _findLock(a_theLock, &recordNum, a_fd, a_object, 1003708dafbfSAlexander Pyhalov a_key); 10045c51f124SMoriah Waterland 10055c51f124SMoriah Waterland if (result != FINDLOCK_LOCKED) { 10065c51f124SMoriah Waterland break; 10075c51f124SMoriah Waterland } 10085c51f124SMoriah Waterland 10095c51f124SMoriah Waterland if (_validateLock(a_fd, a_theLock, a_quiet) == B_TRUE) { 10105c51f124SMoriah Waterland break; 10115c51f124SMoriah Waterland } 10125c51f124SMoriah Waterland } 10135c51f124SMoriah Waterland 10145c51f124SMoriah Waterland 10155c51f124SMoriah Waterland /* debug info on result of find of lock */ 10165c51f124SMoriah Waterland 10175c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_ACQUIRE_FINDRESULT, 1018708dafbfSAlexander Pyhalov a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR, 1019708dafbfSAlexander Pyhalov result, recordNum); 10205c51f124SMoriah Waterland 10215c51f124SMoriah Waterland /* determine how to acquire the lock */ 10225c51f124SMoriah Waterland 10235c51f124SMoriah Waterland switch (result) { 10245c51f124SMoriah Waterland /* 10255c51f124SMoriah Waterland * object is not locked but a key was specified 10265c51f124SMoriah Waterland */ 10275c51f124SMoriah Waterland case FINDLOCK_NOTLOCKED: 10285c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR, 1029708dafbfSAlexander Pyhalov MSG_LOCK_ACQUIRE_NOTLOCKED, 1030708dafbfSAlexander Pyhalov a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR, 1031708dafbfSAlexander Pyhalov a_object, a_key); 10325c51f124SMoriah Waterland break; 10335c51f124SMoriah Waterland 10345c51f124SMoriah Waterland /* 10355c51f124SMoriah Waterland * object is locked and no key was specified: 10365c51f124SMoriah Waterland * - if lock is exclusively held, return "locked" 10375c51f124SMoriah Waterland * - if exclusive lock requested, return "locked" 10385c51f124SMoriah Waterland * - otherwise lock is shared and shared lock requested, 10395c51f124SMoriah Waterland * - increment lock count and return the key 10405c51f124SMoriah Waterland */ 10415c51f124SMoriah Waterland case FINDLOCK_LOCKED: 10425c51f124SMoriah Waterland /* return error if current lock exclusive */ 10435c51f124SMoriah Waterland 10445c51f124SMoriah Waterland if (a_theLock->_lrLock.lockExclusive) { 10455c51f124SMoriah Waterland break; 10465c51f124SMoriah Waterland } 10475c51f124SMoriah Waterland 10485c51f124SMoriah Waterland /* return error if requesting exclusive lock */ 10495c51f124SMoriah Waterland 10505c51f124SMoriah Waterland if (a_exclusive) { 10515c51f124SMoriah Waterland break; 10525c51f124SMoriah Waterland } 10535c51f124SMoriah Waterland 10545c51f124SMoriah Waterland /* shared requesting shared - add to shared lock */ 10555c51f124SMoriah Waterland 10565c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, 1057708dafbfSAlexander Pyhalov MSG_LOCK_ACQUIRE_LOCKED_SHARED, 1058708dafbfSAlexander Pyhalov a_object, a_key); 10595c51f124SMoriah Waterland 10605c51f124SMoriah Waterland /* increment shared lock count */ 10615c51f124SMoriah Waterland 10625c51f124SMoriah Waterland if (_incrementLockCount(a_fd, a_theLock) == 0) { 10635c51f124SMoriah Waterland result = FINDLOCK_LOCKACQUIRED; 10645c51f124SMoriah Waterland } else { 10655c51f124SMoriah Waterland result = FINDLOCK_ERROR; 10665c51f124SMoriah Waterland } 10675c51f124SMoriah Waterland 10685c51f124SMoriah Waterland break; 10695c51f124SMoriah Waterland 10705c51f124SMoriah Waterland /* 10715c51f124SMoriah Waterland * object is not locked 10725c51f124SMoriah Waterland */ 10735c51f124SMoriah Waterland case FINDLOCK_NOTFOUND: 10745c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, 1075708dafbfSAlexander Pyhalov MSG_LOCK_ACQUIRE_NOTFOUND, 1076708dafbfSAlexander Pyhalov a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR, 1077708dafbfSAlexander Pyhalov a_object); 10785c51f124SMoriah Waterland 10795c51f124SMoriah Waterland if (_addLock(key, a_fd, a_object, a_exclusive, 1080708dafbfSAlexander Pyhalov a_pid, a_zid) == 0) { 10815c51f124SMoriah Waterland (void) strncpy(a_theLock->_lrLock.lockKey, key, 1082708dafbfSAlexander Pyhalov sizeof (a_theLock->_lrLock.lockKey)); 10835c51f124SMoriah Waterland result = FINDLOCK_LOCKACQUIRED; 10845c51f124SMoriah Waterland } else { 10855c51f124SMoriah Waterland result = FINDLOCK_ERROR; 10865c51f124SMoriah Waterland } 10875c51f124SMoriah Waterland break; 10885c51f124SMoriah Waterland 10895c51f124SMoriah Waterland /* 10905c51f124SMoriah Waterland * object is locked, key specified, specified key does not match 10915c51f124SMoriah Waterland */ 10925c51f124SMoriah Waterland case FINDLOCK_KEYMISMATCH: 10935c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_ERR, 1094708dafbfSAlexander Pyhalov MSG_LOCK_ACQUIRE_KEYMISMATCH, 1095708dafbfSAlexander Pyhalov a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR, 1096708dafbfSAlexander Pyhalov a_object); 10975c51f124SMoriah Waterland break; 10985c51f124SMoriah Waterland 10995c51f124SMoriah Waterland /* 11005c51f124SMoriah Waterland * error determining if object is locked 11015c51f124SMoriah Waterland */ 11025c51f124SMoriah Waterland case FINDLOCK_ERROR: 11035c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_ACQUIRE_ERROR, 1104708dafbfSAlexander Pyhalov a_object, a_key, strerror(errno)); 11055c51f124SMoriah Waterland break; 11065c51f124SMoriah Waterland 11075c51f124SMoriah Waterland /* 11085c51f124SMoriah Waterland * object is locked and specified key matches 11095c51f124SMoriah Waterland */ 11105c51f124SMoriah Waterland case FINDLOCK_FOUND: 11115c51f124SMoriah Waterland /* return locked if object currently locked */ 11125c51f124SMoriah Waterland if (a_exclusive != a_theLock->_lrLock.lockExclusive) { 11135c51f124SMoriah Waterland result = FINDLOCK_LOCKED; 11145c51f124SMoriah Waterland break; 11155c51f124SMoriah Waterland } 11165c51f124SMoriah Waterland 11175c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_ACQUIRE_FOUND_INC, 1118708dafbfSAlexander Pyhalov a_object, a_key, 1119708dafbfSAlexander Pyhalov a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR); 11205c51f124SMoriah Waterland 11215c51f124SMoriah Waterland /* increment shared lock */ 11225c51f124SMoriah Waterland 11235c51f124SMoriah Waterland if (_incrementLockCount(a_fd, a_theLock) == 0) { 11245c51f124SMoriah Waterland result = FINDLOCK_LOCKACQUIRED; 11255c51f124SMoriah Waterland } else { 11265c51f124SMoriah Waterland result = FINDLOCK_ERROR; 11275c51f124SMoriah Waterland } 11285c51f124SMoriah Waterland break; 11295c51f124SMoriah Waterland 11305c51f124SMoriah Waterland /* 11315c51f124SMoriah Waterland * unknown return 11325c51f124SMoriah Waterland */ 11335c51f124SMoriah Waterland default: 11345c51f124SMoriah Waterland result = FINDLOCK_ERROR; 11355c51f124SMoriah Waterland break; 11365c51f124SMoriah Waterland } 11375c51f124SMoriah Waterland 11385c51f124SMoriah Waterland return (result); 11395c51f124SMoriah Waterland } 11405c51f124SMoriah Waterland 11415c51f124SMoriah Waterland /* 11425c51f124SMoriah Waterland * Name: _openLockFile 11435c51f124SMoriah Waterland * Description: open the lock file, acquiring exclusive record locks 11445c51f124SMoriah Waterland * Arguments: 11455c51f124SMoriah Waterland * a_root - root of file system to manipulate locks on 11465c51f124SMoriah Waterland * Returns: int 11475c51f124SMoriah Waterland * >= 0 - successful - file descriptor lock file opened on 11485c51f124SMoriah Waterland * < 0 - not successful 11495c51f124SMoriah Waterland */ 11505c51f124SMoriah Waterland 11515c51f124SMoriah Waterland static int 11525c51f124SMoriah Waterland _openLockFile(char *a_root) 11535c51f124SMoriah Waterland { 11545c51f124SMoriah Waterland WAITER_T waiter; 11555c51f124SMoriah Waterland char lockpath[MAXPATHLEN]; 11565c51f124SMoriah Waterland int fd; 11575c51f124SMoriah Waterland int result; 11585c51f124SMoriah Waterland 11595c51f124SMoriah Waterland /* entry debugging info */ 11605c51f124SMoriah Waterland 11615c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_OPENFILE_ENTRY, 1162708dafbfSAlexander Pyhalov a_root, LOCK_FILENAME); 11635c51f124SMoriah Waterland 11645c51f124SMoriah Waterland /* generate path to lock directory */ 11655c51f124SMoriah Waterland 11665c51f124SMoriah Waterland (void) snprintf(lockpath, sizeof (lockpath), "%s/%s", 1167708dafbfSAlexander Pyhalov a_root, LOCK_DIRECTORY); 11685c51f124SMoriah Waterland 11695c51f124SMoriah Waterland if (access(lockpath, F_OK) != 0) { 11705c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_ROOTDIR_INVALID, 1171708dafbfSAlexander Pyhalov lockpath, strerror(errno)); 11725c51f124SMoriah Waterland return (-1); 11735c51f124SMoriah Waterland } 11745c51f124SMoriah Waterland 11755c51f124SMoriah Waterland /* generate path to lock file */ 11765c51f124SMoriah Waterland 11775c51f124SMoriah Waterland (void) snprintf(lockpath, sizeof (lockpath), 1178708dafbfSAlexander Pyhalov "%s/%s", a_root, LOCK_FILENAME); 11795c51f124SMoriah Waterland 11805c51f124SMoriah Waterland /* wait for open to succeed up to limits */ 11815c51f124SMoriah Waterland 11825c51f124SMoriah Waterland for (waiter = WAITER_INITIAL; 1183708dafbfSAlexander Pyhalov waiter < WAITER_MAX; 1184708dafbfSAlexander Pyhalov waiter = WAITER_NEXT(waiter)) { 11855c51f124SMoriah Waterland 11865c51f124SMoriah Waterland /* LINTED O_CREAT without O_EXCL specified in call to open() */ 11875c51f124SMoriah Waterland fd = open(lockpath, O_CREAT|O_RDWR, LOCK_FILEMODE); 11885c51f124SMoriah Waterland 11895c51f124SMoriah Waterland /* break out of loop if file opened */ 11905c51f124SMoriah Waterland 11915c51f124SMoriah Waterland if (fd >= 0) { 11925c51f124SMoriah Waterland break; 11935c51f124SMoriah Waterland } 11945c51f124SMoriah Waterland 11955c51f124SMoriah Waterland /* failed - exit loop if due to access (permissions) failure */ 11965c51f124SMoriah Waterland 11975c51f124SMoriah Waterland if (errno == EACCES) { 11985c51f124SMoriah Waterland break; 11995c51f124SMoriah Waterland } 12005c51f124SMoriah Waterland 12015c51f124SMoriah Waterland /* file is busy - wait and try again */ 12025c51f124SMoriah Waterland 12035c51f124SMoriah Waterland if (waiter == WAITER_INITIAL) { 12045c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, 1205708dafbfSAlexander Pyhalov MSG_LOCK_OPENFILE_SLEEPING, 1206708dafbfSAlexander Pyhalov strerror(errno), waiter); 12075c51f124SMoriah Waterland } 12085c51f124SMoriah Waterland 12095c51f124SMoriah Waterland (void) sleep(waiter); 12105c51f124SMoriah Waterland } 12115c51f124SMoriah Waterland 12125c51f124SMoriah Waterland /* if open filed generate error message and return error */ 12135c51f124SMoriah Waterland 12145c51f124SMoriah Waterland if (fd < 0) { 12155c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_OPENFILE_FAILURE, 1216708dafbfSAlexander Pyhalov strerror(errno)); 12175c51f124SMoriah Waterland perror(lockpath); 12185c51f124SMoriah Waterland return (-1); 12195c51f124SMoriah Waterland } 12205c51f124SMoriah Waterland 12215c51f124SMoriah Waterland /* 12225c51f124SMoriah Waterland * lock file opened - acquire exclusive section lock on entire file; 12235c51f124SMoriah Waterland * wait for lockf to succeed up to limits 12245c51f124SMoriah Waterland */ 12255c51f124SMoriah Waterland 12265c51f124SMoriah Waterland for (waiter = WAITER_INITIAL; 1227708dafbfSAlexander Pyhalov waiter < WAITER_MAX; 1228708dafbfSAlexander Pyhalov waiter = WAITER_NEXT(waiter)) { 12295c51f124SMoriah Waterland 12305c51f124SMoriah Waterland /* acquire exclusive section lock on entire file */ 12315c51f124SMoriah Waterland 12325c51f124SMoriah Waterland result = lockf(fd, F_LOCK, 0xFFFFF); 12335c51f124SMoriah Waterland 12345c51f124SMoriah Waterland /* break out of loop if entire file locked */ 12355c51f124SMoriah Waterland 12365c51f124SMoriah Waterland if (result == 0) { 12375c51f124SMoriah Waterland break; 12385c51f124SMoriah Waterland } 12395c51f124SMoriah Waterland 12405c51f124SMoriah Waterland /* file is busy - wait and try again */ 12415c51f124SMoriah Waterland 12425c51f124SMoriah Waterland if (waiter == WAITER_INITIAL) { 12435c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_OPENFILE_SLEEP2, 1244708dafbfSAlexander Pyhalov strerror(errno), waiter); 12455c51f124SMoriah Waterland } 12465c51f124SMoriah Waterland 12475c51f124SMoriah Waterland (void) sleep(waiter); 12485c51f124SMoriah Waterland } 12495c51f124SMoriah Waterland 12505c51f124SMoriah Waterland /* if section lock failed generate error message and return error */ 12515c51f124SMoriah Waterland 12525c51f124SMoriah Waterland if (result < 0) { 12535c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_OPENFILE_FAIL2, 1254708dafbfSAlexander Pyhalov strerror(errno)); 12555c51f124SMoriah Waterland perror(lockpath); 12565c51f124SMoriah Waterland (void) close(fd); 12575c51f124SMoriah Waterland return (-1); 12585c51f124SMoriah Waterland } 12595c51f124SMoriah Waterland 12605c51f124SMoriah Waterland /* file opened and locked - return success */ 12615c51f124SMoriah Waterland 12625c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_OPENFILE_SUCCESS, fd); 12635c51f124SMoriah Waterland 12645c51f124SMoriah Waterland return (fd); 12655c51f124SMoriah Waterland } 12665c51f124SMoriah Waterland 12675c51f124SMoriah Waterland /* 12685c51f124SMoriah Waterland * Name: _lockMatch 12695c51f124SMoriah Waterland * Description: Compare two lock objects using file name match criteria 12705c51f124SMoriah Waterland * Arguments: 12715c51f124SMoriah Waterland * a_s1Lock - first lock object to compare against the second 12725c51f124SMoriah Waterland * a_s2Lock - second lock object to compare against the first 12735c51f124SMoriah Waterland * Returns: 12745c51f124SMoriah Waterland * == 0 - the locks match at some level 12755c51f124SMoriah Waterland * != 0 - the locks do not match at any level 12765c51f124SMoriah Waterland */ 12775c51f124SMoriah Waterland 12785c51f124SMoriah Waterland static int 12795c51f124SMoriah Waterland _lockMatch(char *a_s1Lock, char *a_s2Lock) 12805c51f124SMoriah Waterland { 12815c51f124SMoriah Waterland boolean_t s1Sfx = B_FALSE; 12825c51f124SMoriah Waterland boolean_t s2Sfx = B_FALSE; 12835c51f124SMoriah Waterland char *final1Lock = (char *)NULL; 12845c51f124SMoriah Waterland char *final2Lock = (char *)NULL; 12855c51f124SMoriah Waterland char s1Buf[MAXPATHLEN] = {'\0'}; 12865c51f124SMoriah Waterland char s1Prefix[MAXPATHLEN] = {'\0'}; 12875c51f124SMoriah Waterland char s2Buf[MAXPATHLEN] = {'\0'}; 12885c51f124SMoriah Waterland char s2Prefix[MAXPATHLEN] = {'\0'}; 12895c51f124SMoriah Waterland int result = 0; 12905c51f124SMoriah Waterland int s1Cnt; 12915c51f124SMoriah Waterland int s2Cnt; 12925c51f124SMoriah Waterland 12935c51f124SMoriah Waterland /* entry assertions */ 12945c51f124SMoriah Waterland 12955c51f124SMoriah Waterland assert(a_s1Lock != (char *)NULL); 12965c51f124SMoriah Waterland assert(a_s2Lock != (char *)NULL); 12975c51f124SMoriah Waterland 12985c51f124SMoriah Waterland /* entry debugging info */ 12995c51f124SMoriah Waterland 13005c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_ENTRY, a_s1Lock, a_s2Lock); 13015c51f124SMoriah Waterland 13025c51f124SMoriah Waterland /* 13035c51f124SMoriah Waterland * attempt to find a common anchor between the two locks; that is, 13045c51f124SMoriah Waterland * find the first node in the first lock that matches any node 13055c51f124SMoriah Waterland * in the second lock; for example: 13065c51f124SMoriah Waterland * --> a/b/c vs b/c/d 13075c51f124SMoriah Waterland * -> common anchor is "b"; comparison would expand to: 13085c51f124SMoriah Waterland * --> a/b/c/? vs ?/b/c/d 13095c51f124SMoriah Waterland */ 13105c51f124SMoriah Waterland 13115c51f124SMoriah Waterland /* process each node in the first lock */ 13125c51f124SMoriah Waterland 13135c51f124SMoriah Waterland for (s1Cnt = 0; ; s1Cnt++) { 13145c51f124SMoriah Waterland /* get next first lock node */ 13155c51f124SMoriah Waterland 13165c51f124SMoriah Waterland pkgstrGetToken_r((char *)NULL, a_s1Lock, s1Cnt, "/", 1317708dafbfSAlexander Pyhalov s1Buf, sizeof (s1Buf)); 13185c51f124SMoriah Waterland 13195c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_FSTNODE, s1Cnt, s1Buf); 13205c51f124SMoriah Waterland 13215c51f124SMoriah Waterland /* exit if no more nodes left */ 13225c51f124SMoriah Waterland 13235c51f124SMoriah Waterland if (s1Buf[0] == '\0') { 13245c51f124SMoriah Waterland break; 13255c51f124SMoriah Waterland } 13265c51f124SMoriah Waterland 13275c51f124SMoriah Waterland /* discover "." prefix for this node */ 13285c51f124SMoriah Waterland 13295c51f124SMoriah Waterland pkgstrGetToken_r((char *)NULL, s1Buf, 0, ".", s1Prefix, 1330708dafbfSAlexander Pyhalov sizeof (s1Prefix)); 13315c51f124SMoriah Waterland 13325c51f124SMoriah Waterland s1Sfx = (strlen(s1Prefix) == strlen(s1Buf) ? B_FALSE : B_TRUE); 13335c51f124SMoriah Waterland 13345c51f124SMoriah Waterland /* search each second lock node; look for the first node lock */ 13355c51f124SMoriah Waterland 13365c51f124SMoriah Waterland for (s2Cnt = 0; ; s2Cnt++) { 13375c51f124SMoriah Waterland /* get next second lock node */ 13385c51f124SMoriah Waterland 13395c51f124SMoriah Waterland pkgstrGetToken_r((char *)NULL, a_s2Lock, s2Cnt, "/", 1340708dafbfSAlexander Pyhalov s2Buf, sizeof (s2Buf)); 13415c51f124SMoriah Waterland 13425c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_SCNDNODE, s2Cnt, 1343708dafbfSAlexander Pyhalov s2Buf); 13445c51f124SMoriah Waterland 13455c51f124SMoriah Waterland /* exit if no nodes left */ 13465c51f124SMoriah Waterland 13475c51f124SMoriah Waterland if (s2Buf[0] == '\0') { 13485c51f124SMoriah Waterland break; 13495c51f124SMoriah Waterland } 13505c51f124SMoriah Waterland 13515c51f124SMoriah Waterland /* discover "." prefix for this node */ 13525c51f124SMoriah Waterland 13535c51f124SMoriah Waterland pkgstrGetToken_r((char *)NULL, s2Buf, 0, ".", s2Prefix, 1354708dafbfSAlexander Pyhalov sizeof (s2Prefix)); 13555c51f124SMoriah Waterland 13565c51f124SMoriah Waterland s2Sfx = (strlen(s2Prefix) == 1357708dafbfSAlexander Pyhalov strlen(s2Buf) ? B_FALSE : B_TRUE); 13585c51f124SMoriah Waterland 13595c51f124SMoriah Waterland /* 13605c51f124SMoriah Waterland * process this pair of nodes: 13615c51f124SMoriah Waterland * if both nodes do not have a prefix, then directly 13625c51f124SMoriah Waterland * compare the nodes (e.g. a/b vs c/d: a vs c, b vs d) 13635c51f124SMoriah Waterland * and break out of the loop if there is a match; 13645c51f124SMoriah Waterland * otherwise, compare prefixes and break out of the 13655c51f124SMoriah Waterland * loop if there is a match (e.g. a.* / b.* vs 13665c51f124SMoriah Waterland * vs c.* / d.*: a.* vs c.*, a.* vs d.*, b.* vs c.*, 13675c51f124SMoriah Waterland * b.* vs d.*). 13685c51f124SMoriah Waterland */ 13695c51f124SMoriah Waterland 13705c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_NODES, s1Buf, 1371708dafbfSAlexander Pyhalov s1Prefix, s1Sfx, s2Buf, s2Prefix, s2Sfx); 13725c51f124SMoriah Waterland 13735c51f124SMoriah Waterland if ((s1Sfx == B_FALSE) || (s2Sfx == B_FALSE)) { 13745c51f124SMoriah Waterland /* one doesnt have a prefix direct comparison */ 13755c51f124SMoriah Waterland 13765c51f124SMoriah Waterland if (strcmp(s1Buf, s2Buf) == 0) { 13775c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, 1378708dafbfSAlexander Pyhalov MSG_LCKMCH_DIRMCH, 1379708dafbfSAlexander Pyhalov s1Buf, s2Buf); 13805c51f124SMoriah Waterland break; 13815c51f124SMoriah Waterland } 13825c51f124SMoriah Waterland 13835c51f124SMoriah Waterland /* nodes do not directly match, continue */ 13845c51f124SMoriah Waterland 13855c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_DIRNOMCH, 1386708dafbfSAlexander Pyhalov s1Buf, s2Buf); 13875c51f124SMoriah Waterland continue; 13885c51f124SMoriah Waterland } 13895c51f124SMoriah Waterland 13905c51f124SMoriah Waterland /* both have prefix, compare prefixes */ 13915c51f124SMoriah Waterland 13925c51f124SMoriah Waterland if (strcmp(s1Prefix, s2Prefix) == 0) { 13935c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_PFXMCH, 1394708dafbfSAlexander Pyhalov s1Prefix, s2Prefix); 13955c51f124SMoriah Waterland break; 13965c51f124SMoriah Waterland } 13975c51f124SMoriah Waterland 13985c51f124SMoriah Waterland /* prefixes do not match, continue */ 13995c51f124SMoriah Waterland 14005c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_PFXNOMCH, s1Prefix, 1401708dafbfSAlexander Pyhalov s2Prefix); 14025c51f124SMoriah Waterland } 14035c51f124SMoriah Waterland 14045c51f124SMoriah Waterland /* 14055c51f124SMoriah Waterland * match found if not at the end of the second lock node list, 14065c51f124SMoriah Waterland * break out of loop because some match between the two lock 14075c51f124SMoriah Waterland * objects has been found 14085c51f124SMoriah Waterland */ 14095c51f124SMoriah Waterland 14105c51f124SMoriah Waterland if (s2Buf[0] != '\0') { 14115c51f124SMoriah Waterland break; 14125c51f124SMoriah Waterland } 14135c51f124SMoriah Waterland } 14145c51f124SMoriah Waterland 14155c51f124SMoriah Waterland /* 14165c51f124SMoriah Waterland * at this point, either a match has been found between the nodes in 14175c51f124SMoriah Waterland * the two lock objects, or there is no commonality at all between 14185c51f124SMoriah Waterland * the two lock objects. 14195c51f124SMoriah Waterland * 14205c51f124SMoriah Waterland * s1Buf[0] == '\0' && s2Buf[0] == '\0': 14215c51f124SMoriah Waterland * --> nothing in first lock matches anything in second lock: 14225c51f124SMoriah Waterland * ----> (s1Cnt == 1) || (s2Cnt == 1) && (s1Sfx == B_FALSE) 14235c51f124SMoriah Waterland * ----> || (s2Sfx == B_FALSE) 14245c51f124SMoriah Waterland * --------> an absolute lock do not match 14255c51f124SMoriah Waterland * ----> else both object locks have nothing in common - match 14265c51f124SMoriah Waterland * 14275c51f124SMoriah Waterland * s2Buf[0] != '\0' && s1Buf[0] != '\0' && s1Cnt > 0 && s2Cnt > 0 14285c51f124SMoriah Waterland * --> locks have incompatible overlaps - no match, such as: 14295c51f124SMoriah Waterland * ----> a.* / b.* / c.* / d.* and y.* / b.* / c.* 14305c51f124SMoriah Waterland * 14315c51f124SMoriah Waterland * s1Cnt == 0 && s2Cnt == 0: 14325c51f124SMoriah Waterland * --> locks begin with same node - do comparison 14335c51f124SMoriah Waterland * 14345c51f124SMoriah Waterland * s1Cnt != 0 && s2Cnt == 0 && s2Buf[0] != '\0' 14355c51f124SMoriah Waterland * --> second lock is subset of first lock 14365c51f124SMoriah Waterland * 14375c51f124SMoriah Waterland * s2Cnt == 0 && s2Buf[0] != '\0': 14385c51f124SMoriah Waterland * --> s1Buf[s1Cnt] matches s2Buf[0] - second is subset of first 14395c51f124SMoriah Waterland * 14405c51f124SMoriah Waterland * s2Cnt != 0 && s1Cnt == 0 && s1Buf[0] != '\0': 14415c51f124SMoriah Waterland * --> first lock is subset of second lock 14425c51f124SMoriah Waterland * 14435c51f124SMoriah Waterland */ 14445c51f124SMoriah Waterland 14455c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_FSTLCK, s1Cnt, s1Buf, 1446708dafbfSAlexander Pyhalov s1Prefix, s1Sfx); 14475c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_SCNDLCK, s2Cnt, s2Buf, 1448708dafbfSAlexander Pyhalov s2Prefix, s2Sfx); 14495c51f124SMoriah Waterland 14505c51f124SMoriah Waterland /* process any direct comparisons that might be possible */ 14515c51f124SMoriah Waterland 14525c51f124SMoriah Waterland if ((s1Buf[0] == '\0') && (s2Buf[0] == '\0')) { 14535c51f124SMoriah Waterland /* nothing in first matches anything in second lock */ 14545c51f124SMoriah Waterland 14555c51f124SMoriah Waterland if (((s1Cnt == 1) || (s2Cnt == 1)) && 1456708dafbfSAlexander Pyhalov ((s1Sfx == B_FALSE) || (s2Sfx == B_FALSE))) { 14575c51f124SMoriah Waterland /* two absolute locks match (e.g. 'file' and 'dir') */ 14585c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_ABSNOMCH, a_s1Lock, 1459708dafbfSAlexander Pyhalov a_s2Lock); 14605c51f124SMoriah Waterland return (1); 14615c51f124SMoriah Waterland } 14625c51f124SMoriah Waterland 14635c51f124SMoriah Waterland /* two object locks have nothing in common: match */ 14645c51f124SMoriah Waterland 14655c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_OBJMCH, a_s1Lock, a_s2Lock); 14665c51f124SMoriah Waterland 14675c51f124SMoriah Waterland return (0); 14685c51f124SMoriah Waterland } 14695c51f124SMoriah Waterland 14705c51f124SMoriah Waterland if ((s2Buf[0] != '\0') && (s1Buf[0] != '\0') && 1471708dafbfSAlexander Pyhalov (s1Cnt > 0) && (s2Cnt > 0)) { 14725c51f124SMoriah Waterland /* incompatible overlapping objects */ 14735c51f124SMoriah Waterland 14745c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_OVLPNOMCH, a_s1Lock, a_s2Lock, 1475708dafbfSAlexander Pyhalov s1Cnt+1, s1Buf); 14765c51f124SMoriah Waterland 14775c51f124SMoriah Waterland return (1); 14785c51f124SMoriah Waterland } 14795c51f124SMoriah Waterland 14805c51f124SMoriah Waterland /* 14815c51f124SMoriah Waterland * must compare each node of each lock to determine match; 14825c51f124SMoriah Waterland * start off at the first byte of both locks 14835c51f124SMoriah Waterland */ 14845c51f124SMoriah Waterland 14855c51f124SMoriah Waterland final1Lock = a_s1Lock; 14865c51f124SMoriah Waterland final2Lock = a_s2Lock; 14875c51f124SMoriah Waterland 14885c51f124SMoriah Waterland if ((s1Cnt == 0) && (s2Cnt == 0)) { 14895c51f124SMoriah Waterland /* both have first match - start comparison from the begining */ 14905c51f124SMoriah Waterland 14915c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_SAME, a_s1Lock, a_s2Lock, 1492708dafbfSAlexander Pyhalov s1Buf); 14935c51f124SMoriah Waterland 14945c51f124SMoriah Waterland } else if ((s1Cnt != 0) && (s2Cnt == 0) && (s2Buf[0] != '\0')) { 14955c51f124SMoriah Waterland /* second lock begins somewhere inside of the first lock */ 14965c51f124SMoriah Waterland 14975c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_SCNDSUB, a_s2Lock, a_s1Lock, 1498708dafbfSAlexander Pyhalov s1Cnt+1, s1Buf); 14995c51f124SMoriah Waterland 15005c51f124SMoriah Waterland /* advance first lock to matching node in second lock */ 15015c51f124SMoriah Waterland 15025c51f124SMoriah Waterland if (strchr(a_s1Lock, '/') != (char *)NULL) { 15035c51f124SMoriah Waterland for (; s1Cnt > 0 && (*final1Lock != '\0'); 1504708dafbfSAlexander Pyhalov final1Lock++) { 15055c51f124SMoriah Waterland if (*final1Lock == '/') { 15065c51f124SMoriah Waterland s1Cnt--; 15075c51f124SMoriah Waterland } 15085c51f124SMoriah Waterland } 15095c51f124SMoriah Waterland } 15105c51f124SMoriah Waterland } else if ((s2Cnt != 0) && (s1Cnt == 0) && (s1Buf[0] != '\0')) { 15115c51f124SMoriah Waterland /* first lock begins somewhere inside of the second lock */ 15125c51f124SMoriah Waterland 15135c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_FRSTSUB, a_s1Lock, a_s2Lock, 1514708dafbfSAlexander Pyhalov s2Cnt+1, s2Buf); 15155c51f124SMoriah Waterland 15165c51f124SMoriah Waterland /* advance second lock to matching node in first lock */ 15175c51f124SMoriah Waterland 15185c51f124SMoriah Waterland if (strchr(a_s2Lock, '/') != (char *)NULL) { 15195c51f124SMoriah Waterland for (; s2Cnt > 0 && (*final2Lock != '\0'); 1520708dafbfSAlexander Pyhalov final2Lock++) { 15215c51f124SMoriah Waterland if (*final2Lock == '/') { 15225c51f124SMoriah Waterland s2Cnt--; 15235c51f124SMoriah Waterland } 15245c51f124SMoriah Waterland } 15255c51f124SMoriah Waterland } 15265c51f124SMoriah Waterland } else { 15275c51f124SMoriah Waterland /* unknown condition (probably impossible): directly compare */ 15285c51f124SMoriah Waterland 15295c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LCKMCH_DONTKNOW, a_s1Lock, a_s2Lock); 15305c51f124SMoriah Waterland } 15315c51f124SMoriah Waterland 15325c51f124SMoriah Waterland /* 15335c51f124SMoriah Waterland * locks have common node - compare from that node forward 15345c51f124SMoriah Waterland */ 15355c51f124SMoriah Waterland 15365c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_READY, final1Lock, final2Lock); 15375c51f124SMoriah Waterland 15385c51f124SMoriah Waterland /* compare each node (prefix) - success when no more nodes to compare */ 15395c51f124SMoriah Waterland 15405c51f124SMoriah Waterland for (s1Cnt = 0; ; s1Cnt++) { 15415c51f124SMoriah Waterland /* get next node from first lock */ 15425c51f124SMoriah Waterland 15435c51f124SMoriah Waterland pkgstrGetToken_r((char *)NULL, final1Lock, s1Cnt, "/", s1Buf, 1544708dafbfSAlexander Pyhalov sizeof (s1Buf)); 15455c51f124SMoriah Waterland 15465c51f124SMoriah Waterland /* success if at end of lock */ 15475c51f124SMoriah Waterland 15485c51f124SMoriah Waterland if (s1Buf[0] == '\0') { 15495c51f124SMoriah Waterland break; 15505c51f124SMoriah Waterland } 15515c51f124SMoriah Waterland 15525c51f124SMoriah Waterland /* get next node from second lock */ 15535c51f124SMoriah Waterland 15545c51f124SMoriah Waterland pkgstrGetToken_r((char *)NULL, final2Lock, s1Cnt, "/", s2Buf, 1555708dafbfSAlexander Pyhalov sizeof (s2Buf)); 15565c51f124SMoriah Waterland 15575c51f124SMoriah Waterland /* success if at end of lock */ 15585c51f124SMoriah Waterland 15595c51f124SMoriah Waterland if (s2Buf[0] == '\0') { 15605c51f124SMoriah Waterland break; 15615c51f124SMoriah Waterland } 15625c51f124SMoriah Waterland 15635c51f124SMoriah Waterland /* compare both nodes */ 15645c51f124SMoriah Waterland 15655c51f124SMoriah Waterland result = fnmatch(s1Buf, s2Buf, 0); 15665c51f124SMoriah Waterland if (result != 0) { 15675c51f124SMoriah Waterland result = fnmatch(s2Buf, s1Buf, 0); 15685c51f124SMoriah Waterland } 15695c51f124SMoriah Waterland 15705c51f124SMoriah Waterland /* failure if nodes do not match */ 15715c51f124SMoriah Waterland 15725c51f124SMoriah Waterland if (result != 0) { 15735c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_NODEFAIL, 1574708dafbfSAlexander Pyhalov s1Cnt, s1Buf, s2Buf); 15755c51f124SMoriah Waterland return (1); 15765c51f124SMoriah Waterland } 15775c51f124SMoriah Waterland 15785c51f124SMoriah Waterland /* nodes match, continue and compare next set of nodes */ 15795c51f124SMoriah Waterland 15805c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_NODEOK, s1Cnt, s1Buf, s2Buf); 15815c51f124SMoriah Waterland } 15825c51f124SMoriah Waterland 15835c51f124SMoriah Waterland /* no more nodes to compare - locks match */ 15845c51f124SMoriah Waterland 15855c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LCKMCH_MATCHOK, final1Lock, final2Lock); 15865c51f124SMoriah Waterland 15875c51f124SMoriah Waterland return (0); 15885c51f124SMoriah Waterland } 15895c51f124SMoriah Waterland 15905c51f124SMoriah Waterland /* 15915c51f124SMoriah Waterland * Name: _findLock 15925c51f124SMoriah Waterland * Description: Locate specified lock in lock file 15935c51f124SMoriah Waterland * Arguments: 15945c51f124SMoriah Waterland * a_theLock - lock object filled with contents of lock (if found) 15955c51f124SMoriah Waterland * r_recordNum - will contain record number if lock found 15965c51f124SMoriah Waterland * - will be RECORDNUM_NONE if lock not found 15975c51f124SMoriah Waterland * a_fd - file descriptor opened on the lock file 15985c51f124SMoriah Waterland * a_key - key associated with lock to look up 15995c51f124SMoriah Waterland * a_object - object associated with lock to look up 16005c51f124SMoriah Waterland * Returns: 16015c51f124SMoriah Waterland * FINDLOCK_FOUND - specified lock found; a_theLock contains contents 16025c51f124SMoriah Waterland * of found lock, r_recordNum contain record number of lock 16035c51f124SMoriah Waterland * FINDLOCK_ERROR - failed - error occurred looking up the lock 16045c51f124SMoriah Waterland * FINDLOCK_NOTFOUND - specified object is not locked 16055c51f124SMoriah Waterland * FINDLOCK_KEYMISMATCH - object lock found but specified key doesnt match 16065c51f124SMoriah Waterland * FINDLOCK_LOCKED - object lock found but no key specified 16075c51f124SMoriah Waterland * FINDLOCK_NOTLOCKED - object not locked 16085c51f124SMoriah Waterland */ 16095c51f124SMoriah Waterland 16105c51f124SMoriah Waterland static FINDLOCK_T 16115c51f124SMoriah Waterland _findLock(LOCK_T *a_theLock, RECORDNUM_T *r_recordNum, 1612708dafbfSAlexander Pyhalov int a_fd, char *a_object, char *a_key) 16135c51f124SMoriah Waterland { 16145c51f124SMoriah Waterland ADMINLOCK_T *pll; 16155c51f124SMoriah Waterland char *pld; 16165c51f124SMoriah Waterland int recordNum = 0; 16175c51f124SMoriah Waterland long pls; 16185c51f124SMoriah Waterland off_t pos; 16195c51f124SMoriah Waterland 16205c51f124SMoriah Waterland /* reset returned record number to "none" */ 16215c51f124SMoriah Waterland 16225c51f124SMoriah Waterland *r_recordNum = RECORDNUM_NONE; 16235c51f124SMoriah Waterland 16245c51f124SMoriah Waterland /* localize references to lock object */ 16255c51f124SMoriah Waterland 16265c51f124SMoriah Waterland pld = &a_theLock->_lrLockData[0]; 16275c51f124SMoriah Waterland pll = &a_theLock->_lrLock; 16285c51f124SMoriah Waterland pls = sizeof (a_theLock->_lrLockData); 16295c51f124SMoriah Waterland 16305c51f124SMoriah Waterland /* zero out returned lock data */ 16315c51f124SMoriah Waterland 16325c51f124SMoriah Waterland bzero(pld, pls); 16335c51f124SMoriah Waterland 16345c51f124SMoriah Waterland /* debug info before processing lock file */ 16355c51f124SMoriah Waterland 16365c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_FINDLOCK_ENTRY, 1637708dafbfSAlexander Pyhalov a_object, a_key); 16385c51f124SMoriah Waterland 16395c51f124SMoriah Waterland /* rewind to beginning of lock file */ 16405c51f124SMoriah Waterland 16415c51f124SMoriah Waterland pos = lseek(a_fd, 0L, SEEK_SET); 16425c51f124SMoriah Waterland if (pos == (off_t)-1) { 16435c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_FINDLOCK_LSEEK_FAILURE, 1644708dafbfSAlexander Pyhalov a_object, a_key, strerror(errno)); 16455c51f124SMoriah Waterland return (FINDLOCK_ERROR); 16465c51f124SMoriah Waterland } 16475c51f124SMoriah Waterland 16485c51f124SMoriah Waterland /* read and process each lock */ 16495c51f124SMoriah Waterland 16505c51f124SMoriah Waterland for (; pread(a_fd, pld, pls, pls*recordNum) == pls; recordNum++) { 16515c51f124SMoriah Waterland /* debug info on this lock */ 16525c51f124SMoriah Waterland 16535c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_FINDLOCK_READRECORD, 1654708dafbfSAlexander Pyhalov recordNum, pll->lockCount, 1655708dafbfSAlexander Pyhalov pll->lockObject, pll->lockKey, pll->lockPid, 1656708dafbfSAlexander Pyhalov pll->lockZoneId); 16575c51f124SMoriah Waterland 16585c51f124SMoriah Waterland /* continue if object is not the one we are looking for */ 16595c51f124SMoriah Waterland 16605c51f124SMoriah Waterland if (_lockMatch(a_object, pll->lockObject) != 0) { 16615c51f124SMoriah Waterland continue; 16625c51f124SMoriah Waterland } 16635c51f124SMoriah Waterland 16645c51f124SMoriah Waterland /* 16655c51f124SMoriah Waterland * object found; return locked if searching for no key 16665c51f124SMoriah Waterland */ 16675c51f124SMoriah Waterland 16685c51f124SMoriah Waterland if (*a_key == '\0') { 16695c51f124SMoriah Waterland /* no key specified - object is locked */ 16705c51f124SMoriah Waterland *r_recordNum = recordNum; 16715c51f124SMoriah Waterland return (FINDLOCK_LOCKED); 16725c51f124SMoriah Waterland } 16735c51f124SMoriah Waterland 16745c51f124SMoriah Waterland /* 16755c51f124SMoriah Waterland * object found and keys present; see if keys match 16765c51f124SMoriah Waterland */ 16775c51f124SMoriah Waterland 16785c51f124SMoriah Waterland if (strcmp(pll->lockKey, a_key) != 0) { 16795c51f124SMoriah Waterland /* keys do not match */ 16805c51f124SMoriah Waterland *r_recordNum = recordNum; 16815c51f124SMoriah Waterland return (FINDLOCK_KEYMISMATCH); 16825c51f124SMoriah Waterland } 16835c51f124SMoriah Waterland 16845c51f124SMoriah Waterland /* object found and keys match - return match */ 16855c51f124SMoriah Waterland 16865c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_FINDLOCK_FOUND); 16875c51f124SMoriah Waterland 16885c51f124SMoriah Waterland *r_recordNum = recordNum; 16895c51f124SMoriah Waterland return (FINDLOCK_FOUND); 16905c51f124SMoriah Waterland } 16915c51f124SMoriah Waterland 16925c51f124SMoriah Waterland /* object not locked - return error if key supplied */ 16935c51f124SMoriah Waterland 16945c51f124SMoriah Waterland if (*a_key != '\0') { 16955c51f124SMoriah Waterland return (FINDLOCK_NOTLOCKED); 16965c51f124SMoriah Waterland } 16975c51f124SMoriah Waterland 16985c51f124SMoriah Waterland /* object not locked and key not supplied - no lock found */ 16995c51f124SMoriah Waterland 17005c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_FINDLOCK_NOTFOUND); 17015c51f124SMoriah Waterland 17025c51f124SMoriah Waterland return (FINDLOCK_NOTFOUND); 17035c51f124SMoriah Waterland } 17045c51f124SMoriah Waterland 17055c51f124SMoriah Waterland /* 17065c51f124SMoriah Waterland * Name: _addLock 17075c51f124SMoriah Waterland * Description: Add a new lock to the lock file 17085c51f124SMoriah Waterland * Arguments: 17095c51f124SMoriah Waterland * r_key - if lock acquired key is placed here 17105c51f124SMoriah Waterland * a_fd - file descriptor opened on the lock file 17115c51f124SMoriah Waterland * a_object - object to lock 17125c51f124SMoriah Waterland * a_exclusive - type of lock to add: 17135c51f124SMoriah Waterland * == 0 - shared lock 17145c51f124SMoriah Waterland * != 0 - exclusive lock 17155c51f124SMoriah Waterland * a_pid - if != 0 process i.d. to associate with this lock 17165c51f124SMoriah Waterland * a_zid - if >= 0 zone i.d. to associate with this lock 17175c51f124SMoriah Waterland * Returns: int 17185c51f124SMoriah Waterland * == 0 - success 17195c51f124SMoriah Waterland * != 0 - failure 17205c51f124SMoriah Waterland */ 17215c51f124SMoriah Waterland 17225c51f124SMoriah Waterland static int 17235c51f124SMoriah Waterland _addLock(char *r_key, int a_fd, char *a_object, int a_exclusive, pid_t a_pid, 1724708dafbfSAlexander Pyhalov zoneid_t a_zid) 17255c51f124SMoriah Waterland { 17265c51f124SMoriah Waterland LOCK_T theLock; 17275c51f124SMoriah Waterland char *key; 17285c51f124SMoriah Waterland off_t pos; 17295c51f124SMoriah Waterland ssize_t result; 17305c51f124SMoriah Waterland 17315c51f124SMoriah Waterland /* get unique i.d. for this lock */ 17325c51f124SMoriah Waterland 17335c51f124SMoriah Waterland key = _getUniqueId(); 17345c51f124SMoriah Waterland 17355c51f124SMoriah Waterland /* determine record number for next record in lock file */ 17365c51f124SMoriah Waterland 17375c51f124SMoriah Waterland pos = lseek(a_fd, 0L, SEEK_END); 17385c51f124SMoriah Waterland if (pos == (off_t)-1) { 17395c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_ADDLOCK_LSEEK_FAILURE, 1740708dafbfSAlexander Pyhalov a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR, 1741708dafbfSAlexander Pyhalov a_object, strerror(errno)); 17425c51f124SMoriah Waterland return (1); 17435c51f124SMoriah Waterland } 17445c51f124SMoriah Waterland 17455c51f124SMoriah Waterland /* allocate storace for this lock */ 17465c51f124SMoriah Waterland 17475c51f124SMoriah Waterland bzero(&theLock, sizeof (theLock)); 17485c51f124SMoriah Waterland 17495c51f124SMoriah Waterland /* fill in components of the lock */ 17505c51f124SMoriah Waterland 17515c51f124SMoriah Waterland (void) strlcpy(theLock._lrLock.lockObject, a_object, 1752708dafbfSAlexander Pyhalov LOCK_OBJECT_MAXLEN); 17535c51f124SMoriah Waterland (void) strlcpy(theLock._lrLock.lockKey, key, LOCK_KEY_MAXLEN); 17545c51f124SMoriah Waterland theLock._lrLock.lockCount = 1; 17555c51f124SMoriah Waterland theLock._lrLock.lockPid = (a_pid > 0 ? a_pid : 0); 17565c51f124SMoriah Waterland theLock._lrLock.lockRecordNum = (pos == 0 ? 0 : (pos/sizeof (LOCK_T))); 17575c51f124SMoriah Waterland theLock._lrLock.lockExclusive = a_exclusive; 17585c51f124SMoriah Waterland theLock._lrLock.lockZoneId = (a_zid >= 0 ? a_zid : -1); 17595c51f124SMoriah Waterland 17605c51f124SMoriah Waterland /* debug info on new lock */ 17615c51f124SMoriah Waterland 17625c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_ADDLOCK_ADDING, 1763708dafbfSAlexander Pyhalov a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR, 1764708dafbfSAlexander Pyhalov pos, theLock._lrLock.lockObject, theLock._lrLock.lockKey, 1765708dafbfSAlexander Pyhalov theLock._lrLock.lockPid, theLock._lrLock.lockZoneId); 17665c51f124SMoriah Waterland 17675c51f124SMoriah Waterland /* write the new lock record to the end of the lock file */ 17685c51f124SMoriah Waterland 17695c51f124SMoriah Waterland result = pwrite(a_fd, &theLock, LOCK_SIZE, pos); 17705c51f124SMoriah Waterland if (result != LOCK_SIZE) { 17715c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_ADDLOCK_PWRITE_FAILURE, 1772708dafbfSAlexander Pyhalov a_exclusive ? MSG_LOCK_EXC : MSG_LOCK_SHR, 1773708dafbfSAlexander Pyhalov a_object, strerror(errno)); 17745c51f124SMoriah Waterland return (1); 17755c51f124SMoriah Waterland } 17765c51f124SMoriah Waterland 17775c51f124SMoriah Waterland /* output the key assigned to standard out */ 17785c51f124SMoriah Waterland 17795c51f124SMoriah Waterland (void) strncpy(r_key, key, LOCK_KEY_MAXLEN); 17805c51f124SMoriah Waterland 17815c51f124SMoriah Waterland return (0); 17825c51f124SMoriah Waterland } 17835c51f124SMoriah Waterland 17845c51f124SMoriah Waterland static int 17855c51f124SMoriah Waterland _incrementLockCount(int a_fd, LOCK_T *a_theLock) 17865c51f124SMoriah Waterland { 17875c51f124SMoriah Waterland ADMINLOCK_T *pll; 17885c51f124SMoriah Waterland char *pld; 17895c51f124SMoriah Waterland long pls; 17905c51f124SMoriah Waterland ssize_t result; 17915c51f124SMoriah Waterland 17925c51f124SMoriah Waterland /* localize references to lock object */ 17935c51f124SMoriah Waterland 17945c51f124SMoriah Waterland pld = &a_theLock->_lrLockData[0]; 17955c51f124SMoriah Waterland pll = &a_theLock->_lrLock; 17965c51f124SMoriah Waterland pls = sizeof (a_theLock->_lrLockData); 17975c51f124SMoriah Waterland 17985c51f124SMoriah Waterland /* debug info on incrementing lock */ 17995c51f124SMoriah Waterland 18005c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_INCLOCK_ENTRY, 1801708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 1802708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 1803708dafbfSAlexander Pyhalov pll->lockRecordNum, pll->lockCount); 18045c51f124SMoriah Waterland 18055c51f124SMoriah Waterland /* increment lock count */ 18065c51f124SMoriah Waterland 18075c51f124SMoriah Waterland pll->lockCount++; 18085c51f124SMoriah Waterland 18095c51f124SMoriah Waterland /* write out updated lock */ 18105c51f124SMoriah Waterland 18115c51f124SMoriah Waterland result = pwrite(a_fd, pld, pls, pll->lockRecordNum*pls); 18125c51f124SMoriah Waterland if (result != pls) { 18135c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_INCLOCK_PWRITE_FAILURE, 1814708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 1815708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 1816708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockObject, 1817708dafbfSAlexander Pyhalov strerror(errno)); 18185c51f124SMoriah Waterland return (1); 18195c51f124SMoriah Waterland } 18205c51f124SMoriah Waterland 18215c51f124SMoriah Waterland /* debug info lock incremented */ 18225c51f124SMoriah Waterland 18235c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_INCLOCK_DONE, 1824708dafbfSAlexander Pyhalov pll->lockRecordNum, pll->lockCount, 1825708dafbfSAlexander Pyhalov pll->lockObject, pll->lockKey); 18265c51f124SMoriah Waterland 18275c51f124SMoriah Waterland return (0); 18285c51f124SMoriah Waterland } 18295c51f124SMoriah Waterland 18305c51f124SMoriah Waterland /* 18315c51f124SMoriah Waterland * Name: _validateLock 18325c51f124SMoriah Waterland * Description: determine if a specified lock is valid; if the lock is not valid 18335c51f124SMoriah Waterland * then remove the lock 18345c51f124SMoriah Waterland * Arguments: a_fd - file descriptor opened on the lock file 18355c51f124SMoriah Waterland * a_theLock - lock object to validate 18365c51f124SMoriah Waterland * Returns: boolean_t 18375c51f124SMoriah Waterland * B_TRUE - the lock is valid 18385c51f124SMoriah Waterland * B_FALSE - the lock is not valid and has been removed 18395c51f124SMoriah Waterland */ 18405c51f124SMoriah Waterland 18415c51f124SMoriah Waterland static boolean_t 18425c51f124SMoriah Waterland _validateLock(int a_fd, LOCK_T *a_theLock, int a_quiet) 18435c51f124SMoriah Waterland { 18445c51f124SMoriah Waterland ADMINLOCK_T *pll; 18455c51f124SMoriah Waterland char path[MAXPATHLEN]; 18465c51f124SMoriah Waterland 18475c51f124SMoriah Waterland /* localize references to lock object */ 18485c51f124SMoriah Waterland 18495c51f124SMoriah Waterland pll = &a_theLock->_lrLock; 18505c51f124SMoriah Waterland 18515c51f124SMoriah Waterland /* return true if no process i.d. associated with lock */ 18525c51f124SMoriah Waterland 18535c51f124SMoriah Waterland if (pll->lockPid <= 0) { 18545c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_VALID_NOPID, pll->lockObject); 18555c51f124SMoriah Waterland return (B_TRUE); 18565c51f124SMoriah Waterland } 18575c51f124SMoriah Waterland 18585c51f124SMoriah Waterland /* see if the zone i.d. matches */ 18595c51f124SMoriah Waterland 18605c51f124SMoriah Waterland if (pll->lockZoneId != getzoneid()) { 18615c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_VALID_BADZID, pll->lockObject, 1862708dafbfSAlexander Pyhalov pll->lockZoneId, getzoneid()); 18635c51f124SMoriah Waterland return (B_TRUE); 18645c51f124SMoriah Waterland } else { 18655c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_VALID_ZIDOK, pll->lockObject, 1866708dafbfSAlexander Pyhalov pll->lockZoneId, getzoneid()); 18675c51f124SMoriah Waterland } 18685c51f124SMoriah Waterland 18695c51f124SMoriah Waterland /* see if the process is still active */ 18705c51f124SMoriah Waterland 18715c51f124SMoriah Waterland pkgstrPrintf_r(path, sizeof (path), "/proc/%d", pll->lockPid); 18725c51f124SMoriah Waterland if (access(path, F_OK) == 0) { 18735c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_VALID_OK, pll->lockObject, 1874708dafbfSAlexander Pyhalov pll->lockPid, path); 18755c51f124SMoriah Waterland return (B_TRUE); 18765c51f124SMoriah Waterland } 18775c51f124SMoriah Waterland 18785c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_VALID_NOTOK, pll->lockObject, pll->lockPid, 1879708dafbfSAlexander Pyhalov path); 18805c51f124SMoriah Waterland 18815c51f124SMoriah Waterland /* delete this lock */ 18825c51f124SMoriah Waterland 18835c51f124SMoriah Waterland log_msg(a_quiet ? LOG_MSG_DEBUG : LOG_MSG_WRN, 1884708dafbfSAlexander Pyhalov MSG_VALID_STALE, pll->lockObject, pll->lockPid, 1885708dafbfSAlexander Pyhalov pll->lockZoneId); 18865c51f124SMoriah Waterland 18875c51f124SMoriah Waterland _decrementLockCount(a_fd, a_theLock); 18885c51f124SMoriah Waterland 18895c51f124SMoriah Waterland return (B_FALSE); 18905c51f124SMoriah Waterland } 18915c51f124SMoriah Waterland 18925c51f124SMoriah Waterland static int 18935c51f124SMoriah Waterland _decrementLockCount(int a_fd, LOCK_T *a_theLock) 18945c51f124SMoriah Waterland { 18955c51f124SMoriah Waterland ADMINLOCK_T *pll; 18965c51f124SMoriah Waterland LOCK_T tmpLock; 18975c51f124SMoriah Waterland RECORDNUM_T lastRecord; 18985c51f124SMoriah Waterland char *pld; 18995c51f124SMoriah Waterland long pls; 19005c51f124SMoriah Waterland off_t lastPos; 19015c51f124SMoriah Waterland ssize_t result; 19025c51f124SMoriah Waterland int res; 19035c51f124SMoriah Waterland 19045c51f124SMoriah Waterland /* localize references to lock object */ 19055c51f124SMoriah Waterland 19065c51f124SMoriah Waterland pld = &a_theLock->_lrLockData[0]; 19075c51f124SMoriah Waterland pll = &a_theLock->_lrLock; 19085c51f124SMoriah Waterland pls = sizeof (a_theLock->_lrLockData); 19095c51f124SMoriah Waterland 19105c51f124SMoriah Waterland /* decrement lock count */ 19115c51f124SMoriah Waterland 19125c51f124SMoriah Waterland pll->lockCount--; 19135c51f124SMoriah Waterland 19145c51f124SMoriah Waterland /* if lock count > 0 then write out and leave locked */ 19155c51f124SMoriah Waterland 19165c51f124SMoriah Waterland if (pll->lockCount > 0) { 19175c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_DECLOCK_DECING, 1918708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 1919708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 1920708dafbfSAlexander Pyhalov pll->lockRecordNum, pll->lockCount); 19215c51f124SMoriah Waterland 19225c51f124SMoriah Waterland result = pwrite(a_fd, pld, pls, pll->lockRecordNum*pls); 19235c51f124SMoriah Waterland if (result != pls) { 19245c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_PWRITE_FAILURE, 1925708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 1926708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 1927708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockObject, 1928708dafbfSAlexander Pyhalov strerror(errno)); 19295c51f124SMoriah Waterland return (1); 19305c51f124SMoriah Waterland } 19315c51f124SMoriah Waterland 19325c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_DECLOCK_DONE, 1933708dafbfSAlexander Pyhalov pll->lockRecordNum, pll->lockCount, 1934708dafbfSAlexander Pyhalov pll->lockObject, pll->lockKey); 19355c51f124SMoriah Waterland 19365c51f124SMoriah Waterland return (0); 19375c51f124SMoriah Waterland } 19385c51f124SMoriah Waterland 19395c51f124SMoriah Waterland /* 19405c51f124SMoriah Waterland * lock count zero - erase the record 19415c51f124SMoriah Waterland */ 19425c51f124SMoriah Waterland 19435c51f124SMoriah Waterland /* find last record in the lock file */ 19445c51f124SMoriah Waterland 19455c51f124SMoriah Waterland lastPos = lseek(a_fd, 0L, SEEK_END); /* get size of lock file */ 19465c51f124SMoriah Waterland if (lastPos == (off_t)-1) { 19475c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_LSEEK_FAILURE, 1948708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 1949708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 1950708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockObject, 1951708dafbfSAlexander Pyhalov strerror(errno)); 19525c51f124SMoriah Waterland return (1); 19535c51f124SMoriah Waterland } 19545c51f124SMoriah Waterland 19555c51f124SMoriah Waterland lastRecord = (lastPos/pls)-1; /* convert size to record # */ 19565c51f124SMoriah Waterland 19575c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_DECLOCK_REMOVE, 1958708dafbfSAlexander Pyhalov lastPos, lastRecord, pll->lockRecordNum); 19595c51f124SMoriah Waterland 19605c51f124SMoriah Waterland /* see if removing last record of file */ 19615c51f124SMoriah Waterland 19625c51f124SMoriah Waterland if (lastRecord == pll->lockRecordNum) { 19635c51f124SMoriah Waterland /* debug info removing last record */ 19645c51f124SMoriah Waterland 19655c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_DECLOCK_LASTONE, 1966708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 1967708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 1968708dafbfSAlexander Pyhalov lastRecord, lastPos-pls); 19695c51f124SMoriah Waterland 19705c51f124SMoriah Waterland /* removing last record of file, truncate */ 19715c51f124SMoriah Waterland 19725c51f124SMoriah Waterland res = ftruncate(a_fd, lastPos-pls); 19735c51f124SMoriah Waterland if (res == -1) { 19745c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_FTRUNCATE_FAILURE, 1975708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 1976708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 1977708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockObject, 1978708dafbfSAlexander Pyhalov strerror(errno)); 1979708dafbfSAlexander Pyhalov return (1); 19805c51f124SMoriah Waterland } 19815c51f124SMoriah Waterland return (0); 19825c51f124SMoriah Waterland } 19835c51f124SMoriah Waterland 19845c51f124SMoriah Waterland /* 19855c51f124SMoriah Waterland * not removing last record of file: 19865c51f124SMoriah Waterland * read last record, truncate file one record, 19875c51f124SMoriah Waterland * replace record to be removed with last record read 19885c51f124SMoriah Waterland */ 19895c51f124SMoriah Waterland 19905c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_DECLOCK_REMOVING, 1991708dafbfSAlexander Pyhalov pll->lockRecordNum, lastRecord, lastPos-pls); 19925c51f124SMoriah Waterland 19935c51f124SMoriah Waterland /* read in the last record */ 19945c51f124SMoriah Waterland 19955c51f124SMoriah Waterland result = pread(a_fd, tmpLock._lrLockData, pls, lastRecord*pls); 19965c51f124SMoriah Waterland if (result != pls) { 19975c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_PREAD_FAILURE, 1998708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 1999708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 2000708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockObject, 2001708dafbfSAlexander Pyhalov strerror(errno)); 20025c51f124SMoriah Waterland return (1); 20035c51f124SMoriah Waterland 20045c51f124SMoriah Waterland } 20055c51f124SMoriah Waterland 20065c51f124SMoriah Waterland /* truncate lock file removing the last record (just read in) */ 20075c51f124SMoriah Waterland 20085c51f124SMoriah Waterland res = ftruncate(a_fd, lastPos-pls); 20095c51f124SMoriah Waterland if (res == -1) { 20105c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_FTRUNCATE_FAILURE, 2011708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 2012708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 2013708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockObject, 2014708dafbfSAlexander Pyhalov strerror(errno)); 20155c51f124SMoriah Waterland return (1); 20165c51f124SMoriah Waterland } 20175c51f124SMoriah Waterland 20185c51f124SMoriah Waterland /* update record to indicate its new position in the lock file */ 20195c51f124SMoriah Waterland 20205c51f124SMoriah Waterland tmpLock._lrLock.lockRecordNum = pll->lockRecordNum; 20215c51f124SMoriah Waterland 20225c51f124SMoriah Waterland /* write out the updated record to the new location */ 20235c51f124SMoriah Waterland 20245c51f124SMoriah Waterland result = pwrite(a_fd, tmpLock._lrLockData, pls, pll->lockRecordNum*pls); 20255c51f124SMoriah Waterland if (result != pls) { 20265c51f124SMoriah Waterland log_msg(LOG_MSG_ERR, MSG_LOCK_DECLOCK_PWRITE_FAILURE, 2027708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockExclusive ? 2028708dafbfSAlexander Pyhalov MSG_LOCK_EXC : MSG_LOCK_SHR, 2029708dafbfSAlexander Pyhalov a_theLock->_lrLock.lockObject, 2030708dafbfSAlexander Pyhalov strerror(errno)); 20315c51f124SMoriah Waterland return (1); 20325c51f124SMoriah Waterland } 20335c51f124SMoriah Waterland 20345c51f124SMoriah Waterland return (0); 20355c51f124SMoriah Waterland } 20365c51f124SMoriah Waterland 20375c51f124SMoriah Waterland /* 20385c51f124SMoriah Waterland * Name: _getUniqueId 20395c51f124SMoriah Waterland * Description: Generate a unique ID that can be used as a key for a new lock 20405c51f124SMoriah Waterland * Arguments: None 20415c51f124SMoriah Waterland * Returns: char * 20425c51f124SMoriah Waterland * == NULL - error, no key generated 20435c51f124SMoriah Waterland * != NULL - generated key 20445c51f124SMoriah Waterland * NOTE: Any results returned is placed in new storage for the 20455c51f124SMoriah Waterland * calling method. The caller must use 'lu_memFree' to dispose 20465c51f124SMoriah Waterland * of the storage once the results are no longer needed. 20475c51f124SMoriah Waterland */ 20485c51f124SMoriah Waterland 20495c51f124SMoriah Waterland static char * 20505c51f124SMoriah Waterland _getUniqueId(void) 20515c51f124SMoriah Waterland { 20525c51f124SMoriah Waterland char newkey[LOCK_KEY_MAXLEN]; 20535c51f124SMoriah Waterland hrtime_t hretime; 20545c51f124SMoriah Waterland struct tm tstruct; 20555c51f124SMoriah Waterland time_t thetime; 20565c51f124SMoriah Waterland 20575c51f124SMoriah Waterland /* 2058708dafbfSAlexander Pyhalov * generate own unique key - the key is the 20595c51f124SMoriah Waterland * same length as unique uid but contains different information that 20605c51f124SMoriah Waterland * is as unique as can be made - include current hires time (nanosecond 2061708dafbfSAlexander Pyhalov * real timer). Such a unique i.d. will look like: 2062708dafbfSAlexander Pyhalov * 0203104092-1145345-0004e94d6af481a0 20635c51f124SMoriah Waterland */ 20645c51f124SMoriah Waterland 20655c51f124SMoriah Waterland hretime = gethrtime(); 20665c51f124SMoriah Waterland 20675c51f124SMoriah Waterland thetime = time((time_t *)NULL); 20685c51f124SMoriah Waterland (void) localtime_r(&thetime, &tstruct); 20695c51f124SMoriah Waterland 20705c51f124SMoriah Waterland (void) snprintf(newkey, sizeof (newkey), 2071708dafbfSAlexander Pyhalov "%02d%02d%02d%03d-%02d%02d%02d%d-%016llx", tstruct.tm_mday, 2072708dafbfSAlexander Pyhalov tstruct.tm_mon, tstruct.tm_year, tstruct.tm_yday, 2073708dafbfSAlexander Pyhalov tstruct.tm_hour, tstruct.tm_min, tstruct.tm_sec, 2074708dafbfSAlexander Pyhalov tstruct.tm_wday, hretime); 20755c51f124SMoriah Waterland 20765c51f124SMoriah Waterland log_msg(LOG_MSG_DEBUG, MSG_LOCK_GENUID_INTERNAL, newkey); 20775c51f124SMoriah Waterland return (strdup(newkey)); 20785c51f124SMoriah Waterland } 20795c51f124SMoriah Waterland 20805c51f124SMoriah Waterland /* 20815c51f124SMoriah Waterland * Name: sigint_handler 20825c51f124SMoriah Waterland * Synopsis: SIGINT interrupt handler 20835c51f124SMoriah Waterland * Description: Catch the "SIGINT" signal; increment signal_received 20845c51f124SMoriah Waterland * global variable, 20855c51f124SMoriah Waterland * Arguments: signo - [RO, *RO] - (int) 20865c51f124SMoriah Waterland * Signal number that was caught 20875c51f124SMoriah Waterland * Returns: void 20885c51f124SMoriah Waterland */ 20895c51f124SMoriah Waterland 20905c51f124SMoriah Waterland static void 20915c51f124SMoriah Waterland sigint_handler(int a_signo) 20925c51f124SMoriah Waterland { 20935c51f124SMoriah Waterland signal_received++; 20945c51f124SMoriah Waterland } 20955c51f124SMoriah Waterland 20965c51f124SMoriah Waterland /* 20975c51f124SMoriah Waterland * Name: sighup_handler 20985c51f124SMoriah Waterland * Synopsis: SIGHUP interrupt handler 20995c51f124SMoriah Waterland * Description: Catch the "SIGHUP" signal; increment signal_received 21005c51f124SMoriah Waterland * global variable, 21015c51f124SMoriah Waterland * Arguments: signo - [RO, *RO] - (int) 21025c51f124SMoriah Waterland * Signal number that was caught 21035c51f124SMoriah Waterland * Returns: void 21045c51f124SMoriah Waterland */ 21055c51f124SMoriah Waterland 21065c51f124SMoriah Waterland static void 21075c51f124SMoriah Waterland sighup_handler(int a_signo) 21085c51f124SMoriah Waterland { 21095c51f124SMoriah Waterland signal_received++; 21105c51f124SMoriah Waterland } 2111