summaryrefslogtreecommitdiffstats
path: root/maildrop/filelock.C
blob: 535ee3b664156540f2cc5b4545b1971d2088218c (plain)
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
#include	"filelock.h"
#include	"mio.h"
#if HAVE_FCNTL_H
#include	<fcntl.h>
#endif
#if HAVE_SYS_STAT_H
#include        <sys/stat.h>
#endif
#if HAVE_UNISTD_H
#include	<unistd.h>
#endif
#if HAVE_SYS_FILE_H
#include	<sys/file.h>
#endif
#include	<errno.h>

#include	"liblock/config.h"
#include	"liblock/liblock.h"


void FileLock::cleanup()
{
	UnLock();
}

void FileLock::forked()
{
	UnLock();
}

FileLock::FileLock() : fd(-1)
{
}

FileLock::~FileLock()
{
	UnLock();
}

void FileLock::Lock(const char *filename)
{
	UnLock();

	if ((fd=mopen(filename, O_CREAT | O_WRONLY, 0600)) < 0)
		throw "Unable to create flock file.";

	do_filelock(fd);
}


void FileLock::do_filelock(int fd)
{
int	flockrc;

	while ((flockrc=ll_lock_ex(fd)) < 0 && errno == EINTR)
		;

	if (flockrc < 0)
	{
	struct stat stat_buf;

		// FreeBSD has problems locking /dev/null.  Presume that if
		// you're writing to a device file, you know what you're doing.

		if (fstat(fd, &stat_buf) >= 0 && (
			S_ISREG(stat_buf.st_mode) || S_ISDIR(stat_buf.st_mode)))
		{
			return;
		}

		throw "flock() failed.";
	}
}

void FileLock::UnLock()
{
	if (fd >= 0)
	{
		mclose(fd);
		fd= -1;
	}
}