cdb.c 3.9 KB

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