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