dba_cdb.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. | Authors: Sascha Schumann <sascha@schumann.cx> |
  14. | Marcus Boerger <helly@php.net> |
  15. +----------------------------------------------------------------------+
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include "php.h"
  21. #if DBA_CDB
  22. #include "php_cdb.h"
  23. #include <sys/types.h>
  24. #ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #include <fcntl.h>
  28. #if DBA_CDB_BUILTIN
  29. # include "libcdb/cdb.h"
  30. # include "libcdb/cdb_make.h"
  31. # include "libcdb/uint32.h"
  32. #else
  33. # ifdef CDB_INCLUDE_FILE
  34. # include CDB_INCLUDE_FILE
  35. # endif
  36. #endif
  37. #define CDB_INFO \
  38. dba_cdb *cdb = (dba_cdb *) info->dbf
  39. typedef struct {
  40. struct cdb c;
  41. #if DBA_CDB_BUILTIN
  42. struct cdb_make m;
  43. php_stream *file;
  44. int make;
  45. #else
  46. int file;
  47. #endif
  48. uint32 eod; /* size of constant database */
  49. uint32 pos; /* current position for traversing */
  50. } dba_cdb;
  51. DBA_OPEN_FUNC(cdb)
  52. {
  53. #if DBA_CDB_BUILTIN
  54. php_stream* file = 0;
  55. int make;
  56. #else
  57. int file = 0;
  58. #endif
  59. dba_cdb *cdb;
  60. dba_info *pinfo = (dba_info *) info;
  61. switch (info->mode) {
  62. case DBA_READER:
  63. #if DBA_CDB_BUILTIN
  64. make = 0;
  65. file = info->fp;
  66. #else
  67. file = VCWD_OPEN(info->path, O_RDONLY);
  68. if (file < 0) {
  69. *error = "Unable to open file";
  70. return FAILURE;
  71. }
  72. #endif
  73. break;
  74. #if DBA_CDB_BUILTIN
  75. case DBA_TRUNC:
  76. make = 1;
  77. file = info->fp;
  78. break;
  79. case DBA_CREAT:
  80. case DBA_WRITER:
  81. *error = "Update operations are not supported";
  82. return FAILURE; /* not supported */
  83. #endif
  84. default:
  85. *error = "Currently not supported";
  86. return FAILURE;
  87. }
  88. cdb = pemalloc(sizeof(dba_cdb), info->flags&DBA_PERSISTENT);
  89. memset(cdb, 0, sizeof(dba_cdb));
  90. #if DBA_CDB_BUILTIN
  91. if (make) {
  92. cdb_make_start(&cdb->m, file);
  93. } else {
  94. cdb_init(&cdb->c, file);
  95. }
  96. cdb->make = make;
  97. #else
  98. cdb_init(&cdb->c, file);
  99. #endif
  100. cdb->file = file;
  101. pinfo->dbf = cdb;
  102. return SUCCESS;
  103. }
  104. DBA_CLOSE_FUNC(cdb)
  105. {
  106. CDB_INFO;
  107. /* cdb_free does not close associated file */
  108. #if DBA_CDB_BUILTIN
  109. if (cdb->make) {
  110. cdb_make_finish(&cdb->m);
  111. } else {
  112. cdb_free(&cdb->c);
  113. }
  114. #else
  115. cdb_free(&cdb->c);
  116. close(cdb->file);
  117. #endif
  118. pefree(cdb, info->flags&DBA_PERSISTENT);
  119. }
  120. #if DBA_CDB_BUILTIN
  121. # define php_cdb_read(cdb, buf, len, pos) cdb_read(cdb, buf, len, pos)
  122. # define php_cdb_findnext(cdb, key, len) cdb_findnext(cdb, key, len)
  123. # define php_cdb_find(cdb, key, len) cdb_find(cdb, key, len)
  124. #else
  125. # define php_cdb_read(cdb, buf, len, pos) cdb_read(cdb, buf, len, pos)
  126. # define php_cdb_findnext(cdb, key, len) cdb_findnext(cdb, key, len)
  127. # define php_cdb_find(cdb, key, len) cdb_find(cdb, key, len)
  128. #endif
  129. DBA_FETCH_FUNC(cdb)
  130. {
  131. CDB_INFO;
  132. unsigned int len;
  133. char *new_entry = NULL;
  134. #if DBA_CDB_BUILTIN
  135. if (cdb->make)
  136. return NULL; /* database was opened writeonly */
  137. #endif
  138. if (php_cdb_find(&cdb->c, key, keylen) == 1) {
  139. while(skip--) {
  140. if (php_cdb_findnext(&cdb->c, key, keylen) != 1) {
  141. return NULL;
  142. }
  143. }
  144. len = cdb_datalen(&cdb->c);
  145. new_entry = safe_emalloc(len, 1, 1);
  146. if (php_cdb_read(&cdb->c, new_entry, len, cdb_datapos(&cdb->c)) == -1) {
  147. efree(new_entry);
  148. return NULL;
  149. }
  150. new_entry[len] = 0;
  151. if (newlen)
  152. *newlen = len;
  153. }
  154. return new_entry;
  155. }
  156. DBA_UPDATE_FUNC(cdb)
  157. {
  158. #if DBA_CDB_BUILTIN
  159. CDB_INFO;
  160. if (!cdb->make)
  161. return FAILURE; /* database was opened readonly */
  162. if (!mode)
  163. return FAILURE; /* cdb_make doesn't know replace */
  164. if (cdb_make_add(&cdb->m, key, keylen, val, vallen) != -1)
  165. return SUCCESS;
  166. #endif
  167. return FAILURE;
  168. }
  169. DBA_EXISTS_FUNC(cdb)
  170. {
  171. CDB_INFO;
  172. #if DBA_CDB_BUILTIN
  173. if (cdb->make)
  174. return FAILURE; /* database was opened writeonly */
  175. #endif
  176. if (php_cdb_find(&cdb->c, key, keylen) == 1)
  177. return SUCCESS;
  178. return FAILURE;
  179. }
  180. DBA_DELETE_FUNC(cdb)
  181. {
  182. return FAILURE; /* cdb doesn't support delete */
  183. }
  184. /* {{{ cdb_file_read */
  185. #if DBA_CDB_BUILTIN
  186. # define cdb_file_read(fildes, buf, size) php_stream_read(fildes, buf, size)
  187. #else
  188. # define cdb_file_read(fildes, buf, size) read(fildes, buf, size)
  189. #endif
  190. /* }}} */
  191. #define CREAD(n) do { \
  192. if (cdb_file_read(cdb->file, buf, n) < n) return NULL; \
  193. } while (0)
  194. /* {{{ cdb_file_lseek
  195. php_stream_seek does not return actual position */
  196. #if DBA_CDB_BUILTIN
  197. zend_off_t cdb_file_lseek(php_stream *fp, zend_off_t offset, int whence) {
  198. php_stream_seek(fp, offset, whence);
  199. return php_stream_tell(fp);
  200. }
  201. #else
  202. zend_off_t cdb_file_lseek(int fd, zend_off_t offset, int whence) {
  203. return lseek(fd, offset, whence);
  204. }
  205. #endif
  206. /* }}} */
  207. #define CSEEK(n) do { \
  208. if (n >= cdb->eod) return NULL; \
  209. if (cdb_file_lseek(cdb->file, (zend_off_t)n, SEEK_SET) != (zend_off_t) n) return NULL; \
  210. } while (0)
  211. DBA_FIRSTKEY_FUNC(cdb)
  212. {
  213. CDB_INFO;
  214. uint32 klen, dlen;
  215. char buf[8];
  216. char *key;
  217. #if DBA_CDB_BUILTIN
  218. if (cdb->make)
  219. return NULL; /* database was opened writeonly */
  220. #endif
  221. cdb->eod = -1;
  222. CSEEK(0);
  223. CREAD(4);
  224. /* Total length of file in bytes */
  225. uint32_unpack(buf, &cdb->eod);
  226. CSEEK(2048);
  227. CREAD(8);
  228. /* The first four bytes contain the length of the key */
  229. uint32_unpack(buf, &klen);
  230. uint32_unpack(buf + 4, &dlen);
  231. key = safe_emalloc(klen, 1, 1);
  232. if (cdb_file_read(cdb->file, key, klen) < klen) {
  233. efree(key);
  234. key = NULL;
  235. } else {
  236. key[klen] = '\0';
  237. if (newlen) *newlen = klen;
  238. }
  239. /* header + klenlen + dlenlen + klen + dlen */
  240. cdb->pos = 2048 + 4 + 4 + klen + dlen;
  241. return key;
  242. }
  243. DBA_NEXTKEY_FUNC(cdb)
  244. {
  245. CDB_INFO;
  246. uint32 klen, dlen;
  247. char buf[8];
  248. char *key;
  249. #if DBA_CDB_BUILTIN
  250. if (cdb->make)
  251. return NULL; /* database was opened writeonly */
  252. #endif
  253. CSEEK(cdb->pos);
  254. CREAD(8);
  255. uint32_unpack(buf, &klen);
  256. uint32_unpack(buf + 4, &dlen);
  257. key = safe_emalloc(klen, 1, 1);
  258. if (cdb_file_read(cdb->file, key, klen) < klen) {
  259. efree(key);
  260. key = NULL;
  261. } else {
  262. key[klen] = '\0';
  263. if (newlen) *newlen = klen;
  264. }
  265. cdb->pos += 8 + klen + dlen;
  266. return key;
  267. }
  268. DBA_OPTIMIZE_FUNC(cdb)
  269. {
  270. return SUCCESS;
  271. }
  272. DBA_SYNC_FUNC(cdb)
  273. {
  274. /* this is read-only */
  275. return SUCCESS;
  276. }
  277. DBA_INFO_FUNC(cdb)
  278. {
  279. #if DBA_CDB_BUILTIN
  280. if (!strcmp(hnd->name, "cdb")) {
  281. return estrdup(cdb_version());
  282. } else {
  283. return estrdup(cdb_make_version());
  284. }
  285. #else
  286. return estrdup("External");
  287. #endif
  288. }
  289. #endif