xref: /PHP-5.4/ext/dba/libflatfile/flatfile.c (revision c0d060f5)
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