XCache is a fast, stable PHP opcode cacher that has been proven and is now running on production servers under high load. https://xcache.lighttpd.net/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

165 lines
3.3 KiB

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