File: lock.c

package info (click to toggle)
xcache 2.0.0-4
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 1,724 kB
  • sloc: ansic: 8,175; php: 4,557; awk: 285; sh: 135; makefile: 75
file content (157 lines) | stat: -rwxr-xr-x 3,128 bytes parent folder | download | duplicates (3)
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
146
147
148
149
150
151
152
153
154
155
156
157
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <php.h>
#ifndef ZEND_WIN32
typedef int HANDLE;
#	ifndef INVALID_HANDLE_VALUE
#		define INVALID_HANDLE_VALUE -1
#	endif
#	define CloseHandle(h) close(h)
#endif
#include "lock.h"

struct _xc_lock_t {
	HANDLE fd;
	char *pathname;
};

#ifndef ZEND_WIN32
#	include <unistd.h>
#	include <fcntl.h>
#	include <errno.h>
#	define LCK_WR F_WRLCK
#	define LCK_RD F_RDLCK
#	define LCK_UN F_UNLCK
#	define LCK_NB 0
static inline int dolock(xc_lock_t *lck, int type) /* {{{ */
{ 
	int ret;
	struct flock lock;

	lock.l_type = type;
	lock.l_start = 0;
	lock.l_whence = SEEK_SET;
	lock.l_len = 1;
	lock.l_pid = 0;

	do {
		ret = fcntl(lck->fd, F_SETLKW, &lock);
	} while (ret < 0 && errno == EINTR);
	return ret;
}
/* }}} */
#else

#	include <win32/flock.h>
#	include <io.h>
#	include <fcntl.h>
#	include <sys/types.h>
#	include <sys/stat.h>
#	ifndef errno
#		define errno GetLastError()
#	endif
#	define getuid() 0
#	define LCK_WR LOCKFILE_EXCLUSIVE_LOCK
#	define LCK_RD 0
#	define LCK_UN 0
#	define LCK_NB LOCKFILE_FAIL_IMMEDIATELY
static inline int dolock(xc_lock_t *lck, int type) /* {{{ */
{ 
	static OVERLAPPED offset = {0, 0, 0, 0, NULL};

	if (type == LCK_UN) {
		return UnlockFileEx((HANDLE)lck->fd, 0, 1, 0, &offset);
	}
	else {
		return LockFileEx((HANDLE)lck->fd, type, 0, 1, 0, &offset);
	}
}
/* }}} */
#endif

xc_lock_t *xc_fcntl_init(const char *pathname) /* {{{ */
{
	HANDLE fd;
	xc_lock_t *lck;
	int size;
	char *myname;

	if (pathname == NULL) {
		static int i = 0;
		const char default_tmpdir[] = { DEFAULT_SLASH, 't', 'm', 'p', '\0' };
		const char *tmpdir;

		tmpdir = getenv("TEMP");
		if (!tmpdir) {
			tmpdir = getenv("TMP");
			if (!tmpdir) {
				tmpdir = default_tmpdir;
			}
		}
		size = strlen(tmpdir) + sizeof("/.xcache.lock") - 1 + 3 * 10 + 100;
		myname = malloc(size);
		snprintf(myname, size - 1, "%s%c.xcache.%d.%d.%d.lock", tmpdir, DEFAULT_SLASH, (int) getuid(), i ++, rand());
		pathname = myname;
	}
	else {
		myname = NULL;
	}

	fd = (HANDLE) open(pathname, O_RDWR|O_CREAT, 0666);

	if (fd != INVALID_HANDLE_VALUE) {
		lck = malloc(sizeof(lck[0]));

#ifndef __CYGWIN__
		unlink(pathname);
#endif
		lck->fd = fd;
		size = strlen(pathname) + 1;
		lck->pathname = malloc(size);
		memcpy(lck->pathname, pathname, size);
	}
	else {
		fprintf(stderr, "xc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
		lck = NULL;
	}

	if (myname) {
		free(myname);
	}

	return lck;
}
/* }}} */
void xc_fcntl_destroy(xc_lock_t *lck) /* {{{ */
{   
	CloseHandle(lck->fd);
#ifdef __CYGWIN__
	unlink(lck->pathname);
#endif
	free(lck->pathname);
	free(lck);
}
/* }}} */
void xc_fcntl_lock(xc_lock_t *lck) /* {{{ */
{   
	if (dolock(lck, LCK_WR) < 0) {
		fprintf(stderr, "xc_fcntl_lock failed errno:%d", errno);
	}
}
/* }}} */
void xc_fcntl_rdlock(xc_lock_t *lck) /* {{{ */
{   
	if (dolock(lck, LCK_RD) < 0) {
		fprintf(stderr, "xc_fcntl_lock failed errno:%d", errno);
	}
}
/* }}} */
void xc_fcntl_unlock(xc_lock_t *lck) /* {{{ */
{   
	if (dolock(lck, LCK_UN) < 0) {
		fprintf(stderr, "xc_fcntl_unlock failed errno:%d", errno);
	}
}
/* }}} */