1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2014 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 | Authors: Marcus Boerger <helly@php.net> |
16 | based on ext/db/db.c by: |
17 | Rasmus Lerdorf <rasmus@php.net> |
18 | Jim Winstead <jimw@php.net> |
19 +----------------------------------------------------------------------+
20 */
21
22 /* $Id: a1fce218ab7b7d67f4d8eb1c8f931246e35e5247 $ */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "php.h"
29 #include "php_globals.h"
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #if HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include "flatfile.h"
39
40 #define FLATFILE_BLOCK_SIZE 1024
41
42 /*
43 * ret = -1 means that database was opened for read-only
44 * ret = 0 success
45 * ret = 1 key already exists - nothing done
46 */
47
48 /* {{{ flatfile_store
49 */
flatfile_store(flatfile * dba,datum key_datum,datum value_datum,int mode TSRMLS_DC)50 int flatfile_store(flatfile *dba, datum key_datum, datum value_datum, int mode TSRMLS_DC) {
51 if (mode == FLATFILE_INSERT) {
52 if (flatfile_findkey(dba, key_datum TSRMLS_CC)) {
53 return 1;
54 }
55 php_stream_seek(dba->fp, 0L, SEEK_END);
56 php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", key_datum.dsize);
57 php_stream_flush(dba->fp);
58 if (php_stream_write(dba->fp, key_datum.dptr, key_datum.dsize) < key_datum.dsize) {
59 return -1;
60 }
61 php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", value_datum.dsize);
62 php_stream_flush(dba->fp);
63 if (php_stream_write(dba->fp, value_datum.dptr, value_datum.dsize) < value_datum.dsize) {
64 return -1;
65 }
66 } else { /* FLATFILE_REPLACE */
67 flatfile_delete(dba, key_datum TSRMLS_CC);
68 php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", key_datum.dsize);
69 php_stream_flush(dba->fp);
70 if (php_stream_write(dba->fp, key_datum.dptr, key_datum.dsize) < key_datum.dsize) {
71 return -1;
72 }
73 php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", value_datum.dsize);
74 if (php_stream_write(dba->fp, value_datum.dptr, value_datum.dsize) < value_datum.dsize) {
75 return -1;
76 }
77 }
78
79 php_stream_flush(dba->fp);
80 return 0;
81 }
82 /* }}} */
83
84 /* {{{ flatfile_fetch
85 */
flatfile_fetch(flatfile * dba,datum key_datum TSRMLS_DC)86 datum flatfile_fetch(flatfile *dba, datum key_datum TSRMLS_DC) {
87 datum value_datum = {NULL, 0};
88 char buf[16];
89
90 if (flatfile_findkey(dba, key_datum TSRMLS_CC)) {
91 if (php_stream_gets(dba->fp, buf, sizeof(buf))) {
92 value_datum.dsize = atoi(buf);
93 value_datum.dptr = safe_emalloc(value_datum.dsize, 1, 1);
94 value_datum.dsize = php_stream_read(dba->fp, value_datum.dptr, value_datum.dsize);
95 } else {
96 value_datum.dptr = NULL;
97 value_datum.dsize = 0;
98 }
99 }
100 return value_datum;
101 }
102 /* }}} */
103
104 /* {{{ flatfile_delete
105 */
flatfile_delete(flatfile * dba,datum key_datum TSRMLS_DC)106 int flatfile_delete(flatfile *dba, datum key_datum TSRMLS_DC) {
107 char *key = key_datum.dptr;
108 size_t size = key_datum.dsize;
109 size_t buf_size = FLATFILE_BLOCK_SIZE;
110 char *buf = emalloc(buf_size);
111 size_t num;
112 size_t pos;
113
114 php_stream_rewind(dba->fp);
115 while(!php_stream_eof(dba->fp)) {
116 /* read in the length of the key name */
117 if (!php_stream_gets(dba->fp, buf, 15)) {
118 break;
119 }
120 num = atoi(buf);
121 if (num >= buf_size) {
122 buf_size = num + FLATFILE_BLOCK_SIZE;
123 buf = erealloc(buf, buf_size);
124 }
125 pos = php_stream_tell(dba->fp);
126
127 /* read in the key name */
128 num = php_stream_read(dba->fp, buf, num);
129 if (num < 0) {
130 break;
131 }
132
133 if (size == num && !memcmp(buf, key, size)) {
134 php_stream_seek(dba->fp, pos, SEEK_SET);
135 php_stream_putc(dba->fp, 0);
136 php_stream_flush(dba->fp);
137 php_stream_seek(dba->fp, 0L, SEEK_END);
138 efree(buf);
139 return SUCCESS;
140 }
141
142 /* read in the length of the value */
143 if (!php_stream_gets(dba->fp, buf, 15)) {
144 break;
145 }
146 num = atoi(buf);
147 if (num >= buf_size) {
148 buf_size = num + FLATFILE_BLOCK_SIZE;
149 buf = erealloc(buf, buf_size);
150 }
151 /* read in the value */
152 num = php_stream_read(dba->fp, buf, num);
153 if (num < 0) {
154 break;
155 }
156 }
157 efree(buf);
158 return FAILURE;
159 }
160 /* }}} */
161
162 /* {{{ flatfile_findkey
163 */
flatfile_findkey(flatfile * dba,datum key_datum TSRMLS_DC)164 int flatfile_findkey(flatfile *dba, datum key_datum TSRMLS_DC) {
165 size_t buf_size = FLATFILE_BLOCK_SIZE;
166 char *buf = emalloc(buf_size);
167 size_t num;
168 int ret=0;
169 void *key = key_datum.dptr;
170 size_t size = key_datum.dsize;
171
172 php_stream_rewind(dba->fp);
173 while (!php_stream_eof(dba->fp)) {
174 if (!php_stream_gets(dba->fp, buf, 15)) {
175 break;
176 }
177 num = atoi(buf);
178 if (num >= buf_size) {
179 buf_size = num + FLATFILE_BLOCK_SIZE;
180 buf = erealloc(buf, buf_size);
181 }
182 num = php_stream_read(dba->fp, buf, num);
183 if (num < 0) {
184 break;
185 }
186 if (size == num) {
187 if (!memcmp(buf, key, size)) {
188 ret = 1;
189 break;
190 }
191 }
192 if (!php_stream_gets(dba->fp, buf, 15)) {
193 break;
194 }
195 num = atoi(buf);
196 if (num >= buf_size) {
197 buf_size = num + FLATFILE_BLOCK_SIZE;
198 buf = erealloc(buf, buf_size);
199 }
200 num = php_stream_read(dba->fp, buf, num);
201 if (num < 0) {
202 break;
203 }
204 }
205 efree(buf);
206 return ret;
207 }
208 /* }}} */
209
210 /* {{{ flatfile_firstkey
211 */
flatfile_firstkey(flatfile * dba TSRMLS_DC)212 datum flatfile_firstkey(flatfile *dba TSRMLS_DC) {
213 datum res;
214 size_t num;
215 size_t buf_size = FLATFILE_BLOCK_SIZE;
216 char *buf = emalloc(buf_size);
217
218 php_stream_rewind(dba->fp);
219 while(!php_stream_eof(dba->fp)) {
220 if (!php_stream_gets(dba->fp, buf, 15)) {
221 break;
222 }
223 num = atoi(buf);
224 if (num >= buf_size) {
225 buf_size = num + FLATFILE_BLOCK_SIZE;
226 buf = erealloc(buf, buf_size);
227 }
228 num = php_stream_read(dba->fp, buf, num);
229 if (num < 0) {
230 break;
231 }
232 if (*(buf) != 0) {
233 dba->CurrentFlatFilePos = php_stream_tell(dba->fp);
234 res.dptr = buf;
235 res.dsize = num;
236 return res;
237 }
238 if (!php_stream_gets(dba->fp, buf, 15)) {
239 break;
240 }
241 num = atoi(buf);
242 if (num >= buf_size) {
243 buf_size = num + FLATFILE_BLOCK_SIZE;
244 buf = erealloc(buf, buf_size);
245 }
246 num = php_stream_read(dba->fp, buf, num);
247 if (num < 0) {
248 break;
249 }
250 }
251 efree(buf);
252 res.dptr = NULL;
253 res.dsize = 0;
254 return res;
255 }
256 /* }}} */
257
258 /* {{{ flatfile_nextkey
259 */
flatfile_nextkey(flatfile * dba TSRMLS_DC)260 datum flatfile_nextkey(flatfile *dba TSRMLS_DC) {
261 datum res;
262 size_t num;
263 size_t buf_size = FLATFILE_BLOCK_SIZE;
264 char *buf = emalloc(buf_size);
265
266 php_stream_seek(dba->fp, dba->CurrentFlatFilePos, SEEK_SET);
267 while(!php_stream_eof(dba->fp)) {
268 if (!php_stream_gets(dba->fp, buf, 15)) {
269 break;
270 }
271 num = atoi(buf);
272 if (num >= buf_size) {
273 buf_size = num + FLATFILE_BLOCK_SIZE;
274 buf = erealloc(buf, buf_size);
275 }
276 num = php_stream_read(dba->fp, buf, num);
277 if (num < 0) {
278 break;
279 }
280 if (!php_stream_gets(dba->fp, buf, 15)) {
281 break;
282 }
283 num = atoi(buf);
284 if (num >= buf_size) {
285 buf_size = num + FLATFILE_BLOCK_SIZE;
286 buf = erealloc(buf, buf_size);
287 }
288 num = php_stream_read(dba->fp, buf, num);
289 if (num < 0) {
290 break;
291 }
292 if (*(buf)!=0) {
293 dba->CurrentFlatFilePos = php_stream_tell(dba->fp);
294 res.dptr = buf;
295 res.dsize = num;
296 return res;
297 }
298 }
299 efree(buf);
300 res.dptr = NULL;
301 res.dsize = 0;
302 return res;
303 }
304 /* }}} */
305
306 /* {{{ flatfile_version */
flatfile_version()307 char *flatfile_version()
308 {
309 return "1.0, $Id: a1fce218ab7b7d67f4d8eb1c8f931246e35e5247 $";
310 }
311 /* }}} */
312
313 /*
314 * Local variables:
315 * tab-width: 4
316 * c-basic-offset: 4
317 * End:
318 * vim600: sw=4 ts=4 fdm=marker
319 * vim<600: sw=4 ts=4
320 */
321