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.

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