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