source: trunk/xcache/xc_lock.c @ 1154

Last change on this file since 1154 was 1154, checked in by moo, 2 years ago

avoid using rand() without seed. use getpid

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