1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/*
* Worldvisions Weaver Software:
* Copyright (C) 1997-2002 Net Integration Technologies, Inc.
*
* Some handy functions to create/remove /var/lock lockfiles.
*/
#include "wvlockdev.h"
#include "wvfile.h"
#include "strutils.h"
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
WvLockDev::WvLockDev(WvString _devicename)
: devicename(_devicename)
{
const char *p = strrchr(devicename, '/');
if (p)
p++;
else
p = devicename;
lock_count = 0;
filename = WvString("/var/lock/LCK..%s", p);
}
WvLockDev::~WvLockDev()
{
if (lock_count)
{
lock_count = 1;
unlock();
}
}
#if USE_LOCKDEV /* use the liblockdev.a locking routines */
#include <lockdev.h>
bool WvLockDev::lock()
{
if (lock_count)
{
lock_count++;
return true;
}
if (dev_lock(devicename))
return false;
lock_count++;
return true;
}
void WvLockDev::unlock()
{
if (!lock_count) return;
if (!--lock_count)
dev_unlock(devicename, getpid());
}
#else /* !USE_LOCKDEV -- implement our own locking routines */
// note: this function uses the O_EXCL flag to open(), and thus assumes
// that /var/lock is not an NFS-mounted drive (according to the open() man
// page, you need to follow a special procedure to ensure successful NFS
// locking)
//
// Actually there may be other race conditions that we should look into.
bool WvLockDev::lock()
{
pid_t pid;
if (lock_count)
{
lock_count++;
return true;
}
WvFile fd(filename, O_RDWR | O_EXCL | O_CREAT, 0644);
if (fd.isok())
{
// We made a lock file...
fd.print("%10s\n", getpid());
}
else if (fd.geterr() == EEXIST)
{
char *inbuf;
// Lock file is already there! Check for staleness...
sleep(1); // preventing race condition...
fd.open(filename, O_RDONLY);
//fprintf(stderr, "ok: %d\n", fd.isok());
inbuf = trim_string(fd.getline(-1));
//fprintf(stderr, "getline: '%s'\n", inbuf);
if (inbuf)
pid = atoi(inbuf);
else
pid = 0;
//fprintf(stderr, "pid: '%d'\n", pid);
if (pid && pid != -1 && kill(pid, 0) == -1 && errno == ESRCH)
{
// we can create a lockfile now
fd.close();
if (unlink(filename))
return false; // cannot remove lockfile
fd.open(filename, O_RDWR | O_EXCL | O_CREAT, 0644);
fd.print("%10s\n", getpid());
}
else
return false; // device already locked
}
else // some other unexpected error
return false;
lock_count++;
return true;
}
void WvLockDev::unlock()
{
if (!lock_count) return;
if (!--lock_count)
unlink(filename);
}
#endif /* !USE_LOCKDEV */
|