source: trunk/lock.c @ 282

Last change on this file since 282 was 282, checked in by moo, 8 years ago

fix possible alloca() scope problem in lock

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