cdb.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Marcus Boerger <helly@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. /* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include "php.h"
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #ifndef PHP_WIN32
  27. #include <sys/mman.h>
  28. #endif
  29. #ifdef HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #include <string.h>
  33. #include <errno.h>
  34. #include "cdb.h"
  35. #ifndef EPROTO
  36. # define EPROTO -15 /* cdb 0.75's default for PROTOless systems */
  37. #endif
  38. /* {{{ cdb_match */
  39. static int cdb_match(struct cdb *c, char *key, unsigned int len, uint32 pos)
  40. {
  41. char buf[32];
  42. unsigned int n;
  43. while (len > 0) {
  44. n = sizeof(buf);
  45. if (n > len)
  46. n = len;
  47. if (cdb_read(c, buf, n, pos) == -1)
  48. return -1;
  49. if (memcmp(buf, key, n))
  50. return 0;
  51. pos += n;
  52. key += n;
  53. len -= n;
  54. }
  55. return 1;
  56. }
  57. /* }}} */
  58. /* {{{ cdb_hash */
  59. uint32 cdb_hash(char *buf, unsigned int len)
  60. {
  61. uint32 h;
  62. const unsigned char * b = (unsigned char *)buf;
  63. h = CDB_HASHSTART;
  64. while (len--) {
  65. h = ( h + (h << 5)) ^ (*b++);
  66. }
  67. return h;
  68. }
  69. /* }}} */
  70. /* {{{ cdb_free */
  71. void cdb_free(struct cdb *c)
  72. {
  73. }
  74. /* }}} */
  75. /* {{{ cdb_findstart */
  76. void cdb_findstart(struct cdb *c)
  77. {
  78. c->loop = 0;
  79. }
  80. /* }}} */
  81. /* {{{ cdb_init */
  82. void cdb_init(struct cdb *c, php_stream *fp)
  83. {
  84. cdb_free(c);
  85. cdb_findstart(c);
  86. c->fp = fp;
  87. }
  88. /* }}} */
  89. /* {{{ cdb_read */
  90. int cdb_read(struct cdb *c, char *buf, unsigned int len, uint32 pos)
  91. {
  92. if (php_stream_seek(c->fp, pos, SEEK_SET) == -1) {
  93. errno = EPROTO;
  94. return -1;
  95. }
  96. while (len > 0) {
  97. int r;
  98. do {
  99. r = php_stream_read(c->fp, buf, len);
  100. } while ((r == -1) && (errno == EINTR));
  101. if (r == -1)
  102. return -1;
  103. if (r == 0) {
  104. errno = EPROTO;
  105. return -1;
  106. }
  107. buf += r;
  108. len -= r;
  109. }
  110. return 0;
  111. }
  112. /* }}} */
  113. /* {{{ cdb_findnext */
  114. int cdb_findnext(struct cdb *c, char *key, unsigned int len)
  115. {
  116. char buf[8];
  117. uint32 pos;
  118. uint32 u;
  119. if (!c->loop) {
  120. u = cdb_hash(key, len);
  121. if (cdb_read(c, buf, 8, (u << 3) & 2047) == -1)
  122. return -1;
  123. uint32_unpack(buf + 4,&c->hslots);
  124. if (!c->hslots)
  125. return 0;
  126. uint32_unpack(buf, &c->hpos);
  127. c->khash = u;
  128. u >>= 8;
  129. u %= c->hslots;
  130. u <<= 3;
  131. c->kpos = c->hpos + u;
  132. }
  133. while (c->loop < c->hslots) {
  134. if (cdb_read(c, buf, 8, c->kpos) == -1)
  135. return -1;
  136. uint32_unpack(buf + 4, &pos);
  137. if (!pos)
  138. return 0;
  139. c->loop += 1;
  140. c->kpos += 8;
  141. if (c->kpos == c->hpos + (c->hslots << 3))
  142. c->kpos = c->hpos;
  143. uint32_unpack(buf, &u);
  144. if (u == c->khash) {
  145. if (cdb_read(c, buf, 8, pos) == -1)
  146. return -1;
  147. uint32_unpack(buf, &u);
  148. if (u == len)
  149. switch(cdb_match(c, key, len, pos + 8)) {
  150. case -1:
  151. return -1;
  152. case 1:
  153. uint32_unpack(buf + 4, &c->dlen);
  154. c->dpos = pos + 8 + len;
  155. return 1;
  156. }
  157. }
  158. }
  159. return 0;
  160. }
  161. /* }}} */
  162. /* {{{ cdb_find */
  163. int cdb_find(struct cdb *c, char *key, unsigned int len)
  164. {
  165. cdb_findstart(c);
  166. return cdb_findnext(c, key, len);
  167. }
  168. /* }}} */
  169. /* {{{ cdb_version */
  170. char *cdb_version()
  171. {
  172. return "0.75, $Id$";
  173. }
  174. /* }}} */