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:
96014740deSToomas Soome * record number - record position within the lock file
97014740deSToomas Soome * lock count - number of lock holders maintaining this lock
98014740deSToomas Soome * lock object - object being locked
99014740deSToomas Soome * 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
admin_lock(int argc,char ** argv)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;
231*ef150c2bSRichard Lowe int 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);
39726ec61e2SToomas 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) {
413014740deSToomas Soome int rs = 0;
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
lock_acquire(LOCK_T * a_theLock,int * a_fd,char * a_root,char * a_key,char * a_object,int a_quiet,int a_wait,long a_timeout,int a_exclusive,char * a_altRoot,pid_t a_pid,zoneid_t a_zid)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
lock_release(int a_fd,char * a_key,char * a_object,int a_quiet)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
lock_status(int a_fd,char * a_key,char * a_object,int a_quiet)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
_lock_acquire(LOCK_T * a_theLock,int a_fd,char * a_key,char * a_object,int a_quiet,int a_exclusive,pid_t a_pid,zoneid_t a_zid)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
_openLockFile(char * a_root)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:
1274014740deSToomas Soome * == 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
_lockMatch(char * a_s1Lock,char * a_s2Lock)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;
1291014740deSToomas Soome int s2Cnt = 0;
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
_findLock(LOCK_T * a_theLock,RECORDNUM_T * r_recordNum,int a_fd,char * a_object,char * a_key)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
_addLock(char * r_key,int a_fd,char * a_object,int a_exclusive,pid_t a_pid,zoneid_t a_zid)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
_incrementLockCount(int a_fd,LOCK_T * a_theLock)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
_validateLock(int a_fd,LOCK_T * a_theLock,int a_quiet)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
_decrementLockCount(int a_fd,LOCK_T * a_theLock)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
2044014740deSToomas Soome * 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 *
_getUniqueId(void)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:
2062014740deSToomas Soome * 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
sigint_handler(int a_signo)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
sighup_handler(int a_signo)21075c51f124SMoriah Waterland sighup_handler(int a_signo)
21085c51f124SMoriah Waterland {
21095c51f124SMoriah Waterland signal_received++;
21105c51f124SMoriah Waterland }
2111