File: wvlockdev.cc

package info (click to toggle)
wvstreams 4.0.2-4
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 6,420 kB
  • ctags: 6,518
  • sloc: cpp: 52,544; sh: 5,770; ansic: 810; makefile: 461; tcl: 114; perl: 18
file content (145 lines) | stat: -rw-r--r-- 2,696 bytes parent folder | download
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 */