lock.c revision 5c51f1241dbbdf2656d0e10011981411ed0c9673
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Module: lock.c
* Public methods:
* admin_lock
* Usage:
* Acquire: -a [ -e | -s ] [ -o obj ] [ -k key ] [ -R root ] [ -q ] \
* [ -w ] [ -W timeout ]
* Release: -r -o object -k key [ -R altRoot ] [ -q ]
* Status: [ -o object ] [ -k key ] [ -R altRoot ] [ -q ]
*/
/* enable extentions to standard Unix libraries */
#define __EXTENSIONS__
/* unix system includes */
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <locale.h>
#include <libgen.h>
#include <errno.h>
#include <assert.h>
#include <time.h>
#include <fnmatch.h>
#include <zone.h>
/* local includes */
#include <libinst.h>
#include <pkglib.h>
#include <pkgerr.h>
#include <keystore.h>
#include "pkgadm.h"
#include "pkgadm_msgs.h"
/* definition and conversion of sleep units */
#define SECONDS(x) ((unsigned int)(x))
/* define how waits are timed */
#define WAITER_NEXT(x) ((x)*2)
typedef unsigned int WAITER_T;
/*
* The administrative lock file resides in /tmp
* It does not survive a reboot
* It consists of fixed length records
* Each record has the following information:
* record number - record position within the lock file
* lock count - number of lock holders maintaining this lock
* lock object - object being locked
* lock key - key needed to manipulate existing lock
* lock exclusive - is the lock exclusive (single locker only)
*/
#define LOCK_KEY_MAXLEN 37
#define LOCK_DIRECTORY "/tmp"
/*
* this is the "well known name" of the lock file that is used by the
* package, patch, and zone administration commands to synchronize their
* various efforts - it must live in a temporary directory that is cleared
* on system reboot but it is NOT a temporary file in that it survives
* the process that creates and updates it - if the format of the lock
* file ever changes, this path should be updated with a later "uuid"
* so that previous (incompatible) pkgadm's will not use the later data.
*/
#define LOCK_FILENAME \
"/tmp/.ai.pkg.zone.lock-afdb66cf-1dd1-11b2-a049-000d560ddc3e"
/* mode to use for LOCK_FILENAME */
#define LOCK_FILEMODE \
/* lock contents types */
typedef unsigned long RECORDNUM_T;
#define RECORDNUM_NONE 0xFFFFFFFF
/* actual lock data */
struct _adminLock
{
unsigned long lockCount;
unsigned long lockExclusive;
};
typedef struct _adminLock ADMINLOCK_T;
/* size of an individual "lock" */
#define LOCK_SIZE sizeof (ADMINLOCK_T)
/* union to allow lock to be accessed as raw or structured data */
union _lockRecord
{
char _lrLockData[LOCK_SIZE];
};
typedef union _lockRecord LOCK_T;
/* return codes from "_findLock" */
typedef unsigned long FINDLOCK_T;
#define FINDLOCK_FOUND ((FINDLOCK_T)0)
/*
* Forward declarations
*/
/* local main function implementation methods */
int a_quiet);
int a_quiet);
/* local utility functions */
static char *_getUniqueId(void);
static int _openLockFile(char *a_root);
static void sighup_handler(int a_signo);
static void sigint_handler(int a_signo);
static int signal_received = 0;
/*
* main methods with external entry points
*/
/*
* Name: admin_lock
* Synopsis: main entry point for pkgadm "lock" subcommand
* Returns: 0 on success, non-zero otherwise.
*/
int
{
char *endptr;
char *p;
char c;
int aFlag = 0; /* acquire lock */
int eFlag = 0; /* exclusive lock */
int fd;
int qFlag = 0; /* quiet */
int rFlag = 0; /* release lock */
int result;
int sFlag = 0; /* shared lock */
int tFlag = 0; /* test comparison */
int wFlag = 0; /* wait */
long WFlag = 0; /* wait timeout */
void (*funcSighup)();
void (*funcSigint)();
switch (c) {
case 'a': /* acquire lock */
aFlag++;
break;
case 'e': /* exclusive lock */
eFlag++;
break;
case 'k': /* lock-key */
return (1);
}
break;
case 'o': /* object */
return (1);
}
break;
case 'p': /* process i.d. */
errno = 0;
endptr = 0;
return (1);
}
return (1);
}
break;
case 'q': /* quiet */
qFlag++;
break;
case 'r': /* release lock */
rFlag++;
break;
case 'R': /* alternative root */
/* if root directory is not absolute path, error */
if (*optarg != '/') {
return (1);
}
/* if root directory does not exist, create it */
/* create top level root directory */
return (1);
}
}
if (mkdirp(p, 0777) != 0) {
return (1);
}
}
return (1);
}
(void) free(p);
break;
case 's': /* shared */
sFlag++;
break;
case 't': /* test comparison */
tFlag++;
break;
case 'w': /* wait */
wFlag++;
break;
case 'W': /* wait with timeout */
errno = 0;
endptr = 0;
return (1);
}
return (1);
}
wFlag++;
break;
case 'z': /* zone i.d. */
errno = 0;
endptr = 0;
return (1);
}
return (1);
}
break;
case ':':
/* LINTED fallthrough on case statement */
case '?':
default:
return (1);
}
}
/*
* validate arguments
*/
/* if -t option is specified, override all other options */
if (tFlag) {
int rs;
int rx;
int a;
/* only 2 or 3 args are valid */
if ((a < 2) || (a > 3)) {
return (1);
}
/* if 3rd argument given, it is return value to check */
if (a == 3) {
}
/* if 3rd argument not given, code to check is code returned */
if (a == 2) {
}
/* report results */
if (a == 2) {
return (rx);
}
}
/* always successful */
}
/* must be no non-option arguments left */
return (1);
}
/* -a and -r cannot be used together */
return (1);
}
/* -e and -s cannot be used together */
return (1);
}
/* -e can only be used if -a is used */
return (1);
}
/* -s can only be used if -a is used */
return (1);
}
/*
* perform the requested operation
*/
/*
* hook SIGINT and SIGHUP interrupts into quit.c's trap handler
*/
/* connect sigint_handler() to SIGINT */
} else {
}
/* connect sighupt_handler() to SIGHUP */
} else {
}
/* release hold on signals */
/* open the lock file */
if (fd < 0) {
return (1);
}
if (aFlag) {
/* set "exclusive" mode based on -e/-s flag used */
if (sFlag) {
exclusive = 0;
} else if (eFlag) {
exclusive = 1;
}
/* acquire lock */
switch (tResult) {
case FINDLOCK_LOCKACQUIRED:
result = 0;
break;
case FINDLOCK_LOCKED:
result = 1;
break;
default:
result = 1;
break;
}
} else if (rFlag) {
/* release lock */
} else {
/* lock status */
}
/* close the lock file */
/* return results of operation */
return (result);
}
/*
* local main function implementation methods
*/
/*
* Name: lock_acquire
* Calls _lock_acquire to attempt lock acquisition.
* Arguments:
* a_theLock - lock object filled with contents of existing lock
* a_fd - file descriptor opened on the lock file
* a_root - root of file system to manipulate locks on
* a_key - key associated with lock to acquire
* a_object - object associated with lock to acquire
* a_wait - wait if lock cannot be acquired flag:
* == 0 - do not wait
* != 0 - wait
* a_timeout - timeout if waiting to acquire busy lock:
* == 0 - no timeout (wait forever)
* != 0 - max # seconds to wait to acquire busy lock
* a_quiet - quiet mode enabled flag
* a_pid - if != 0 process i.d. to associate with this lock
* a_zid - if >= 0 - zone i.d. to associate with this lock
* Returns: int
* == 0 - successful
* != 0 - not successful
*/
static FINDLOCK_T
{
int notified = 0;
int closeOnExit = 0;
/* reset the lock */
/* open file if not open */
if ((*a_fd) < 0) {
if ((*a_fd) < 0) {
return (FINDLOCK_ERROR);
}
closeOnExit++;
}
/* compute time after which acquire times out */
for (;;) {
/* attempt to aquire the lock */
/* return result if any result other than object is locked */
switch (result) {
case FINDLOCK_LOCKACQUIRED:
/* close lock file if opened in this function */
if (closeOnExit) {
*a_fd = -1;
}
return (FINDLOCK_LOCKACQUIRED);
case FINDLOCK_FOUND:
case FINDLOCK_NOTFOUND:
case FINDLOCK_KEYMISMATCH:
case FINDLOCK_NOTLOCKED:
case FINDLOCK_ERROR:
default:
/* close lock file if opened in this function */
if (closeOnExit) {
*a_fd = -1;
}
return (result);
case FINDLOCK_LOCKED:
;
/* FALLTHROUGH */
}
/*
* return error if not waiting for lock OR signal received
*/
if ((a_wait == 0) || (signal_received != 0)) {
a_exclusive ? "" :
/* close lock file if opened in this function */
if (closeOnExit) {
*a_fd = -1;
}
return (FINDLOCK_LOCKED);
}
/* waiting for lock - if timeout specified see if time left */
if (a_timeout > 0) {
/* close lock file if opened in this function */
if (closeOnExit) {
*a_fd = -1;
}
return (FINDLOCK_ERROR);
}
}
/*
* waiting to aquire lock:
* - notify waiting (one time only)
* - close lock file
* - sleep
* - open lock file
* - try again
*/
/* notify once */
if (notified++ == 0) {
a_object);
}
/* close lock file */
/* wait (sleep) */
(void) sleep(LOCK_SLEEP_INTERVAL);
/* open the lock file and try again */
if (*a_fd < 0) {
a_object);
/* close lock file if opened in this function */
if (closeOnExit) {
*a_fd = -1;
}
return (FINDLOCK_ERROR);
}
}
}
/*
* Name: lock_release
* Description: implement lock release
* Arguments:
* a_fd - file descriptor opened on the lock file
* a_key - key associated with lock to release
* a_object - object associated with lock to release
* a_quiet - quiet mode enabled flag
* Returns: int
* == 0 - successful
* != 0 - not successful
*/
static int
{
/* entry debugging info */
/* find the lock to be released */
/* determine how to release the lock if found */
switch (result) {
/*
* object is not locked but a key was specified
*/
case FINDLOCK_NOTLOCKED:
return (result);
/*
* object is locked and no matching key was specified
*/
case FINDLOCK_LOCKED:
return (result);
/*
* object is not locked
*/
case FINDLOCK_NOTFOUND:
return (result);
/*
* object is locked and specified key does not match
*/
case FINDLOCK_KEYMISMATCH:
a_object);
return (result);
/*
* error determining if object is locked
*/
case FINDLOCK_ERROR:
return (result);
/*
* object is locked and specified key matches
*/
case FINDLOCK_FOUND:
break;
/*
* unknown return
*/
default:
break;
}
return (result);
}
/*
* Name: lock_status
* Arguments:
* a_fd - file descriptor opened on the lock file
* a_key - key associated with lock to look up
* a_object - object associated with lock to look up
* a_quiet - quiet mode enabled flag
* Returns: int
* == 0 - successful
* != 0 - not successful
*/
static int
{
RECORDNUM_T recordNum = 0;
char *pld;
int found = 0;
long pls;
/* entry debugging info */
/* localize references to lock object */
/* read and process each lock */
/* debug info on this lock */
pll->lockZoneId);
/* ignore if key specified and key does not match */
if ((*a_key != '\0') &&
continue;
}
/* ignore if object specified and object does not match */
if ((*a_object != '\0') &&
continue;
}
found++;
/* process next lock if quiet operation */
if (a_quiet != 0) {
continue;
}
/* output header if first lock object */
if (found == 1) {
"%2s %2s %3s %8s %3s %9s %37s %s\n",
"i#", "l#", "cnt", "pid", "zid", "lock-type",
"---------------lock-key-------------",
"lock-object");
}
/* output status line for this lock object */
"%2ld %2ld %3ld %8ld %3d %9s %37s %s\n",
}
/* return == 0 if found, != 0 if not found */
return (found == 0 ? 1 : 0);
}
/*
* local utility functions
*/
/*
* Name: _lock_acquire
* Arguments:
* a_theLock - lock object filled with contents of existing lock
* a_fd - file descriptor opened on the lock file
* a_key - key associated with lock to acquire
* a_object - object associated with lock to acquire
* a_quiet - quiet mode enabled flag
* a_pid - if != 0 process i.d. to associate with this lock
* a_zid - if >= 0 zone i.d. to associate with this lock
* Returns: FINDLOCK_T
*/
static FINDLOCK_T
{
/* entry debugging info */
/* is the specified object already locked? */
for (;;) {
a_key);
if (result != FINDLOCK_LOCKED) {
break;
}
break;
}
}
/* debug info on result of find of lock */
/* determine how to acquire the lock */
switch (result) {
/*
* object is not locked but a key was specified
*/
case FINDLOCK_NOTLOCKED:
break;
/*
* object is locked and no key was specified:
* - if lock is exclusively held, return "locked"
* - if exclusive lock requested, return "locked"
* - otherwise lock is shared and shared lock requested,
* - increment lock count and return the key
*/
case FINDLOCK_LOCKED:
/* return error if current lock exclusive */
break;
}
/* return error if requesting exclusive lock */
if (a_exclusive) {
break;
}
/* shared requesting shared - add to shared lock */
/* increment shared lock count */
} else {
}
break;
/*
* object is not locked
*/
case FINDLOCK_NOTFOUND:
a_object);
} else {
}
break;
/*
* object is locked, key specified, specified key does not match
*/
case FINDLOCK_KEYMISMATCH:
a_object);
break;
/*
* error determining if object is locked
*/
case FINDLOCK_ERROR:
break;
/*
* object is locked and specified key matches
*/
case FINDLOCK_FOUND:
/* return locked if object currently locked */
break;
}
/* increment shared lock */
} else {
}
break;
/*
* unknown return
*/
default:
break;
}
return (result);
}
/*
* Name: _openLockFile
* Description: open the lock file, acquiring exclusive record locks
* Arguments:
* a_root - root of file system to manipulate locks on
* Returns: int
* >= 0 - successful - file descriptor lock file opened on
* < 0 - not successful
*/
static int
_openLockFile(char *a_root)
{
char lockpath[MAXPATHLEN];
int fd;
int result;
/* entry debugging info */
/* generate path to lock directory */
return (-1);
}
/* generate path to lock file */
/* wait for open to succeed up to limits */
for (waiter = WAITER_INITIAL;
waiter < WAITER_MAX;
/* LINTED O_CREAT without O_EXCL specified in call to open() */
/* break out of loop if file opened */
if (fd >= 0) {
break;
}
/* failed - exit loop if due to access (permissions) failure */
break;
}
/* file is busy - wait and try again */
if (waiter == WAITER_INITIAL) {
}
}
/* if open filed generate error message and return error */
if (fd < 0) {
return (-1);
}
/*
* lock file opened - acquire exclusive section lock on entire file;
* wait for lockf to succeed up to limits
*/
for (waiter = WAITER_INITIAL;
waiter < WAITER_MAX;
/* acquire exclusive section lock on entire file */
/* break out of loop if entire file locked */
if (result == 0) {
break;
}
/* file is busy - wait and try again */
if (waiter == WAITER_INITIAL) {
}
}
/* if section lock failed generate error message and return error */
if (result < 0) {
return (-1);
}
/* file opened and locked - return success */
return (fd);
}
/*
* Name: _lockMatch
* Description: Compare two lock objects using file name match criteria
* Arguments:
* a_s1Lock - first lock object to compare against the second
* a_s2Lock - second lock object to compare against the first
* Returns:
* == 0 - the locks match at some level
* != 0 - the locks do not match at any level
*/
static int
{
char *final1Lock = (char *)NULL;
char *final2Lock = (char *)NULL;
int result = 0;
int s1Cnt;
int s2Cnt;
/* entry assertions */
/* entry debugging info */
/*
* attempt to find a common anchor between the two locks; that is,
* find the first node in the first lock that matches any node
* in the second lock; for example:
* --> a/b/c vs b/c/d
* -> common anchor is "b"; comparison would expand to:
* --> a/b/c/? vs ?/b/c/d
*/
/* process each node in the first lock */
/* get next first lock node */
/* exit if no more nodes left */
if (s1Buf[0] == '\0') {
break;
}
/* discover "." prefix for this node */
sizeof (s1Prefix));
/* search each second lock node; look for the first node lock */
/* get next second lock node */
s2Buf);
/* exit if no nodes left */
if (s2Buf[0] == '\0') {
break;
}
/* discover "." prefix for this node */
sizeof (s2Prefix));
/*
* process this pair of nodes:
* if both nodes do not have a prefix, then directly
* compare the nodes (e.g. a/b vs c/d: a vs c, b vs d)
* and break out of the loop if there is a match;
* otherwise, compare prefixes and break out of the
* loop if there is a match (e.g. a.* / b.* vs
* vs c.* / d.*: a.* vs c.*, a.* vs d.*, b.* vs c.*,
* b.* vs d.*).
*/
/* one doesnt have a prefix direct comparison */
break;
}
/* nodes do not directly match, continue */
continue;
}
/* both have prefix, compare prefixes */
break;
}
/* prefixes do not match, continue */
s2Prefix);
}
/*
* match found if not at the end of the second lock node list,
* break out of loop because some match between the two lock
* objects has been found
*/
if (s2Buf[0] != '\0') {
break;
}
}
/*
* at this point, either a match has been found between the nodes in
* the two lock objects, or there is no commonality at all between
* the two lock objects.
*
* s1Buf[0] == '\0' && s2Buf[0] == '\0':
* --> nothing in first lock matches anything in second lock:
* ----> (s1Cnt == 1) || (s2Cnt == 1) && (s1Sfx == B_FALSE)
* ----> || (s2Sfx == B_FALSE)
* --------> an absolute lock do not match
* ----> else both object locks have nothing in common - match
*
* s2Buf[0] != '\0' && s1Buf[0] != '\0' && s1Cnt > 0 && s2Cnt > 0
* --> locks have incompatible overlaps - no match, such as:
* ----> a.* / b.* / c.* / d.* and y.* / b.* / c.*
*
* s1Cnt == 0 && s2Cnt == 0:
* --> locks begin with same node - do comparison
*
* s1Cnt != 0 && s2Cnt == 0 && s2Buf[0] != '\0'
* --> second lock is subset of first lock
*
* s2Cnt == 0 && s2Buf[0] != '\0':
* --> s1Buf[s1Cnt] matches s2Buf[0] - second is subset of first
*
* s2Cnt != 0 && s1Cnt == 0 && s1Buf[0] != '\0':
* --> first lock is subset of second lock
*
*/
/* process any direct comparisons that might be possible */
/* nothing in first matches anything in second lock */
/* two absolute locks match (e.g. 'file' and 'dir') */
a_s2Lock);
return (1);
}
/* two object locks have nothing in common: match */
return (0);
}
/* incompatible overlapping objects */
return (1);
}
/*
* must compare each node of each lock to determine match;
* start off at the first byte of both locks
*/
/* both have first match - start comparison from the begining */
s1Buf);
/* second lock begins somewhere inside of the first lock */
/* advance first lock to matching node in second lock */
final1Lock++) {
if (*final1Lock == '/') {
s1Cnt--;
}
}
}
/* first lock begins somewhere inside of the second lock */
/* advance second lock to matching node in first lock */
final2Lock++) {
if (*final2Lock == '/') {
s2Cnt--;
}
}
}
} else {
/* unknown condition (probably impossible): directly compare */
}
/*
* locks have common node - compare from that node forward
*/
/* compare each node (prefix) - success when no more nodes to compare */
/* get next node from first lock */
sizeof (s1Buf));
/* success if at end of lock */
if (s1Buf[0] == '\0') {
break;
}
/* get next node from second lock */
sizeof (s2Buf));
/* success if at end of lock */
if (s2Buf[0] == '\0') {
break;
}
/* compare both nodes */
if (result != 0) {
}
/* failure if nodes do not match */
if (result != 0) {
return (1);
}
/* nodes match, continue and compare next set of nodes */
}
/* no more nodes to compare - locks match */
return (0);
}
/*
* Name: _findLock
* Description: Locate specified lock in lock file
* Arguments:
* a_theLock - lock object filled with contents of lock (if found)
* r_recordNum - will contain record number if lock found
* - will be RECORDNUM_NONE if lock not found
* a_fd - file descriptor opened on the lock file
* a_key - key associated with lock to look up
* a_object - object associated with lock to look up
* Returns:
* FINDLOCK_FOUND - specified lock found; a_theLock contains contents
* of found lock, r_recordNum contain record number of lock
* FINDLOCK_ERROR - failed - error occurred looking up the lock
* FINDLOCK_NOTFOUND - specified object is not locked
* FINDLOCK_KEYMISMATCH - object lock found but specified key doesnt match
* FINDLOCK_LOCKED - object lock found but no key specified
* FINDLOCK_NOTLOCKED - object not locked
*/
static FINDLOCK_T
{
char *pld;
int recordNum = 0;
long pls;
/* reset returned record number to "none" */
/* localize references to lock object */
/* zero out returned lock data */
/* debug info before processing lock file */
/* rewind to beginning of lock file */
return (FINDLOCK_ERROR);
}
/* read and process each lock */
/* debug info on this lock */
pll->lockZoneId);
/* continue if object is not the one we are looking for */
continue;
}
/*
* object found; return locked if searching for no key
*/
if (*a_key == '\0') {
/* no key specified - object is locked */
*r_recordNum = recordNum;
return (FINDLOCK_LOCKED);
}
/*
* object found and keys present; see if keys match
*/
/* keys do not match */
*r_recordNum = recordNum;
return (FINDLOCK_KEYMISMATCH);
}
/* object found and keys match - return match */
*r_recordNum = recordNum;
return (FINDLOCK_FOUND);
}
/* object not locked - return error if key supplied */
if (*a_key != '\0') {
return (FINDLOCK_NOTLOCKED);
}
/* object not locked and key not supplied - no lock found */
return (FINDLOCK_NOTFOUND);
}
/*
* Name: _addLock
* Description: Add a new lock to the lock file
* Arguments:
* r_key - if lock acquired key is placed here
* a_fd - file descriptor opened on the lock file
* a_object - object to lock
* a_exclusive - type of lock to add:
* == 0 - shared lock
* != 0 - exclusive lock
* a_pid - if != 0 process i.d. to associate with this lock
* a_zid - if >= 0 zone i.d. to associate with this lock
* Returns: int
* == 0 - success
* != 0 - failure
*/
static int
{
char *key;
/* get unique i.d. for this lock */
key = _getUniqueId();
/* determine record number for next record in lock file */
return (1);
}
/* allocate storace for this lock */
/* fill in components of the lock */
/* debug info on new lock */
/* write the new lock record to the end of the lock file */
return (1);
}
/* output the key assigned to standard out */
return (0);
}
static int
{
char *pld;
long pls;
/* localize references to lock object */
/* debug info on incrementing lock */
/* increment lock count */
/* write out updated lock */
return (1);
}
/* debug info lock incremented */
return (0);
}
/*
* Name: _validateLock
* Description: determine if a specified lock is valid; if the lock is not valid
* then remove the lock
* Arguments: a_fd - file descriptor opened on the lock file
* a_theLock - lock object to validate
* Returns: boolean_t
* B_TRUE - the lock is valid
* B_FALSE - the lock is not valid and has been removed
*/
static boolean_t
{
char *pld;
long pls;
char path[MAXPATHLEN];
/* localize references to lock object */
/* return true if no process i.d. associated with lock */
return (B_TRUE);
}
/* see if the zone i.d. matches */
return (B_TRUE);
} else {
}
/* see if the process is still active */
return (B_TRUE);
}
path);
/* delete this lock */
pll->lockZoneId);
return (B_FALSE);
}
static int
{
char *pld;
long pls;
int res;
/* localize references to lock object */
/* decrement lock count */
/* if lock count > 0 then write out and leave locked */
return (1);
}
return (0);
}
/*
* lock count zero - erase the record
*/
/* find last record in the lock file */
return (1);
}
/* see if removing last record of file */
/* debug info removing last record */
/* removing last record of file, truncate */
if (res == -1) {
return (1);
}
return (0);
}
/*
* not removing last record of file:
* read last record, truncate file one record,
* replace record to be removed with last record read
*/
/* read in the last record */
return (1);
}
/* truncate lock file removing the last record (just read in) */
if (res == -1) {
return (1);
}
/* update record to indicate its new position in the lock file */
/* write out the updated record to the new location */
return (1);
}
return (0);
}
/*
* Name: _getUniqueId
* Description: Generate a unique ID that can be used as a key for a new lock
* Arguments: None
* Returns: char *
* == NULL - error, no key generated
* != NULL - generated key
* NOTE: Any results returned is placed in new storage for the
* calling method. The caller must use 'lu_memFree' to dispose
* of the storage once the results are no longer needed.
*/
static char *
_getUniqueId(void)
{
char *args[10];
char *execResults;
char newkey[LOCK_KEY_MAXLEN];
int b;
int execStatus;
/*
* try and use makeuuid to generate a unique i.d. Such a unique i.d.
* will look like:
* 7814e3c1-1dd2-11b2-9fe8-000d560ddc82
*/
args[0] = "makeuuid";
char *p;
if (p != (char *)NULL) {
*p = '\0';
}
return (execResults);
}
/*
* cannot run makeuuid - generate own unique key - the key is the
* same length as unique uid but contains different information that
* is as unique as can be made - include current hires time (nanosecond
* real timer. Such a unique i.d. will look like:
* 0203104092-1145345-0004e94d6af481a0
*/
}
/*
* Name: sigint_handler
* Synopsis: SIGINT interrupt handler
* Description: Catch the "SIGINT" signal; increment signal_received
* global variable,
* Arguments: signo - [RO, *RO] - (int)
* Signal number that was caught
* Returns: void
*/
static void
sigint_handler(int a_signo)
{
}
/*
* Name: sighup_handler
* Synopsis: SIGHUP interrupt handler
* Description: Catch the "SIGHUP" signal; increment signal_received
* global variable,
* Arguments: signo - [RO, *RO] - (int)
* Signal number that was caught
* Returns: void
*/
static void
sighup_handler(int a_signo)
{
}