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