source: trunk/lock.c @ 928

Last change on this file since 928 was 928, checked in by moo, 22 months ago

fix locking for win32

  • Property svn:eol-style set to native
File size: 3.2 KB
RevLine 
[1]1#include <stdio.h>
2#include <string.h>
[36]3#include <stdlib.h>
[1]4
5#include <php.h>
6#ifndef ZEND_WIN32
7typedef int HANDLE;
[62]8#   ifndef INVALID_HANDLE_VALUE
9#       define INVALID_HANDLE_VALUE -1
10#   endif
[928]11#else
12#   define close(h) CloseHandle(h)
13#   define open(filename, mode, permission) CreateFile(filename, \
14        GENERIC_READ | GENERIC_WRITE, \
15        FILE_SHARE_READ | FILE_SHARE_WRITE, \
16        NULL, \
17        OPEN_ALWAYS, \
18        FILE_ATTRIBUTE_NORMAL, \
19        NULL)
[1]20#endif
21#include "lock.h"
22
23struct _xc_lock_t {
24    HANDLE fd;
25    char *pathname;
26};
27
28#ifndef ZEND_WIN32
29#   include <unistd.h>
30#   include <fcntl.h>
31#   include <errno.h>
[11]32#   define LCK_WR F_WRLCK
33#   define LCK_RD F_RDLCK
34#   define LCK_UN F_UNLCK
35#   define LCK_NB 0
[1]36static inline int dolock(xc_lock_t *lck, int type) /* {{{ */
37{ 
38    int ret;
39    struct flock lock;
40
41    lock.l_type = type;
42    lock.l_start = 0;
43    lock.l_whence = SEEK_SET;
44    lock.l_len = 1;
45    lock.l_pid = 0;
46
47    do {
48        ret = fcntl(lck->fd, F_SETLKW, &lock);
49    } while (ret < 0 && errno == EINTR);
50    return ret;
51}
52/* }}} */
53#else
54
55#   include <win32/flock.h>
56#   include <io.h>
57#   include <fcntl.h>
58#   include <sys/types.h>
59#   include <sys/stat.h>
[928]60#   undef errno
61#   define errno GetLastError()
[11]62#   define getuid() 0
63#   define LCK_WR LOCKFILE_EXCLUSIVE_LOCK
64#   define LCK_RD 0
65#   define LCK_UN 0
66#   define LCK_NB LOCKFILE_FAIL_IMMEDIATELY
[1]67static inline int dolock(xc_lock_t *lck, int type) /* {{{ */
68{ 
69    static OVERLAPPED offset = {0, 0, 0, 0, NULL};
70
71    if (type == LCK_UN) {
[11]72        return UnlockFileEx((HANDLE)lck->fd, 0, 1, 0, &offset);
[1]73    }
74    else {
[11]75        return LockFileEx((HANDLE)lck->fd, type, 0, 1, 0, &offset);
[1]76    }
77}
78/* }}} */
79#endif
80
81xc_lock_t *xc_fcntl_init(const char *pathname) /* {{{ */
82{
83    HANDLE fd;
[62]84    xc_lock_t *lck;
85    int size;
86    char *myname;
[1]87
88    if (pathname == NULL) {
89        static int i = 0;
[62]90        const char default_tmpdir[] = { DEFAULT_SLASH, 't', 'm', 'p', '\0' };
91        const char *tmpdir;
92
93        tmpdir = getenv("TEMP");
94        if (!tmpdir) {
95            tmpdir = getenv("TMP");
96            if (!tmpdir) {
97                tmpdir = default_tmpdir;
98            }
99        }
100        size = strlen(tmpdir) + sizeof("/.xcache.lock") - 1 + 3 * 10 + 100;
[282]101        myname = malloc(size);
[62]102        snprintf(myname, size - 1, "%s%c.xcache.%d.%d.%d.lock", tmpdir, DEFAULT_SLASH, (int) getuid(), i ++, rand());
[1]103        pathname = myname;
104    }
[62]105    else {
106        myname = NULL;
107    }
[1]108
[928]109    fd = open(pathname, O_RDWR|O_CREAT, 0666);
[1]110
[62]111    if (fd != INVALID_HANDLE_VALUE) {
112        lck = malloc(sizeof(lck[0]));
[1]113
114#ifndef __CYGWIN__
115        unlink(pathname);
116#endif
117        lck->fd = fd;
118        size = strlen(pathname) + 1;
119        lck->pathname = malloc(size);
120        memcpy(lck->pathname, pathname, size);
121    }
122    else {
[928]123        zend_error(E_ERROR, "xc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
[62]124        lck = NULL;
[1]125    }
[62]126
127    if (myname) {
[282]128        free(myname);
[62]129    }
130
131    return lck;
[1]132}
133/* }}} */
134void xc_fcntl_destroy(xc_lock_t *lck) /* {{{ */
135{   
[928]136    close(lck->fd);
[1]137#ifdef __CYGWIN__
138    unlink(lck->pathname);
139#endif
140    free(lck->pathname);
141    free(lck);
142}
143/* }}} */
144void xc_fcntl_lock(xc_lock_t *lck) /* {{{ */
145{   
146    if (dolock(lck, LCK_WR) < 0) {
[928]147        zend_error(E_ERROR, "xc_fcntl_lock failed errno:%d", errno);
[1]148    }
149}
150/* }}} */
151void xc_fcntl_rdlock(xc_lock_t *lck) /* {{{ */
152{   
153    if (dolock(lck, LCK_RD) < 0) {
[928]154        zend_error(E_ERROR, "xc_fcntl_lock failed errno:%d", errno);
[1]155    }
156}
157/* }}} */
158void xc_fcntl_unlock(xc_lock_t *lck) /* {{{ */
159{   
160    if (dolock(lck, LCK_UN) < 0) {
[928]161        zend_error(E_ERROR, "xc_fcntl_unlock failed errno:%d", errno);
[1]162    }
163}
164/* }}} */
Note: See TracBrowser for help on using the repository browser.