xref: /PHP-7.3/ext/dba/libflatfile/flatfile.c (revision a6519d05)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 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: 464bb5af8f2e8462a17d20bf000e48ae24de5bd3 $ */
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)50 int flatfile_store(flatfile *dba, datum key_datum, datum value_datum, int mode) {
51 	if (mode == FLATFILE_INSERT) {
52 		if (flatfile_findkey(dba, key_datum)) {
53 			return 1;
54 		}
55 		php_stream_seek(dba->fp, 0L, SEEK_END);
56 		php_stream_printf(dba->fp, "%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, "%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);
68 		php_stream_printf(dba->fp, "%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, "%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)86 datum flatfile_fetch(flatfile *dba, datum key_datum) {
87 	datum value_datum = {NULL, 0};
88 	char buf[16];
89 
90 	if (flatfile_findkey(dba, key_datum)) {
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)106 int flatfile_delete(flatfile *dba, datum key_datum) {
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 
130 		if (size == num && !memcmp(buf, key, size)) {
131 			php_stream_seek(dba->fp, pos, SEEK_SET);
132 			php_stream_putc(dba->fp, 0);
133 			php_stream_flush(dba->fp);
134 			php_stream_seek(dba->fp, 0L, SEEK_END);
135 			efree(buf);
136 			return SUCCESS;
137 		}
138 
139 		/* read in the length of the value */
140 		if (!php_stream_gets(dba->fp, buf, 15)) {
141 			break;
142 		}
143 		num = atoi(buf);
144 		if (num >= buf_size) {
145 			buf_size = num + FLATFILE_BLOCK_SIZE;
146 			buf = erealloc(buf, buf_size);
147 		}
148 		/* read in the value */
149 		num = php_stream_read(dba->fp, buf, num);
150 	}
151 	efree(buf);
152 	return FAILURE;
153 }
154 /* }}} */
155 
156 /* {{{ flatfile_findkey
157  */
flatfile_findkey(flatfile * dba,datum key_datum)158 int flatfile_findkey(flatfile *dba, datum key_datum) {
159 	size_t buf_size = FLATFILE_BLOCK_SIZE;
160 	char *buf = emalloc(buf_size);
161 	size_t num;
162 	int ret=0;
163 	void *key = key_datum.dptr;
164 	size_t size = key_datum.dsize;
165 
166 	php_stream_rewind(dba->fp);
167 	while (!php_stream_eof(dba->fp)) {
168 		if (!php_stream_gets(dba->fp, buf, 15)) {
169 			break;
170 		}
171 		num = atoi(buf);
172 		if (num >= buf_size) {
173 			buf_size = num + FLATFILE_BLOCK_SIZE;
174 			buf = erealloc(buf, buf_size);
175 		}
176 		num = php_stream_read(dba->fp, buf, num);
177 
178 		if (size == num) {
179 			if (!memcmp(buf, key, size)) {
180 				ret = 1;
181 				break;
182 			}
183 		}
184 		if (!php_stream_gets(dba->fp, buf, 15)) {
185 			break;
186 		}
187 		num = atoi(buf);
188 		if (num >= buf_size) {
189 			buf_size = num + FLATFILE_BLOCK_SIZE;
190 			buf = erealloc(buf, buf_size);
191 		}
192 		num = php_stream_read(dba->fp, buf, num);
193 	}
194 	efree(buf);
195 	return ret;
196 }
197 /* }}} */
198 
199 /* {{{ flatfile_firstkey
200  */
flatfile_firstkey(flatfile * dba)201 datum flatfile_firstkey(flatfile *dba) {
202 	datum res;
203 	size_t num;
204 	size_t buf_size = FLATFILE_BLOCK_SIZE;
205 	char *buf = emalloc(buf_size);
206 
207 	php_stream_rewind(dba->fp);
208 	while(!php_stream_eof(dba->fp)) {
209 		if (!php_stream_gets(dba->fp, buf, 15)) {
210 			break;
211 		}
212 		num = atoi(buf);
213 		if (num >= buf_size) {
214 			buf_size = num + FLATFILE_BLOCK_SIZE;
215 			buf = erealloc(buf, buf_size);
216 		}
217 		num = php_stream_read(dba->fp, buf, num);
218 
219 		if (*(buf) != 0) {
220 			dba->CurrentFlatFilePos = php_stream_tell(dba->fp);
221 			res.dptr = buf;
222 			res.dsize = num;
223 			return res;
224 		}
225 		if (!php_stream_gets(dba->fp, buf, 15)) {
226 			break;
227 		}
228 		num = atoi(buf);
229 		if (num >= buf_size) {
230 			buf_size = num + FLATFILE_BLOCK_SIZE;
231 			buf = erealloc(buf, buf_size);
232 		}
233 		num = php_stream_read(dba->fp, buf, num);
234 	}
235 	efree(buf);
236 	res.dptr = NULL;
237 	res.dsize = 0;
238 	return res;
239 }
240 /* }}} */
241 
242 /* {{{ flatfile_nextkey
243  */
flatfile_nextkey(flatfile * dba)244 datum flatfile_nextkey(flatfile *dba) {
245 	datum res;
246 	size_t num;
247 	size_t buf_size = FLATFILE_BLOCK_SIZE;
248 	char *buf = emalloc(buf_size);
249 
250 	php_stream_seek(dba->fp, dba->CurrentFlatFilePos, SEEK_SET);
251 	while(!php_stream_eof(dba->fp)) {
252 		if (!php_stream_gets(dba->fp, buf, 15)) {
253 			break;
254 		}
255 		num = atoi(buf);
256 		if (num >= buf_size) {
257 			buf_size = num + FLATFILE_BLOCK_SIZE;
258 			buf = erealloc(buf, buf_size);
259 		}
260 		num = php_stream_read(dba->fp, buf, num);
261 
262 		if (!php_stream_gets(dba->fp, buf, 15)) {
263 			break;
264 		}
265 		num = atoi(buf);
266 		if (num >= buf_size) {
267 			buf_size = num + FLATFILE_BLOCK_SIZE;
268 			buf = erealloc(buf, buf_size);
269 		}
270 		num = php_stream_read(dba->fp, buf, num);
271 
272 		if (*(buf)!=0) {
273 			dba->CurrentFlatFilePos = php_stream_tell(dba->fp);
274 			res.dptr = buf;
275 			res.dsize = num;
276 			return res;
277 		}
278 	}
279 	efree(buf);
280 	res.dptr = NULL;
281 	res.dsize = 0;
282 	return res;
283 }
284 /* }}} */
285 
286 /* {{{ flatfile_version */
flatfile_version()287 char *flatfile_version()
288 {
289 	return "1.0, $Id: 464bb5af8f2e8462a17d20bf000e48ae24de5bd3 $";
290 }
291 /* }}} */
292 
293 /*
294  * Local variables:
295  * tab-width: 4
296  * c-basic-offset: 4
297  * End:
298  * vim600: sw=4 ts=4 fdm=marker
299  * vim<600: sw=4 ts=4
300  */
301