|
3034
|
1 /***********************************************************
|
|
|
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
|
|
|
3 The Netherlands.
|
|
|
4
|
|
|
5 All Rights Reserved
|
|
|
6
|
|
|
7 Permission to use, copy, modify, and distribute this software and its
|
|
|
8 documentation for any purpose and without fee is hereby granted,
|
|
|
9 provided that the above copyright notice appear in all copies and that
|
|
|
10 both that copyright notice and this permission notice appear in
|
|
|
11 supporting documentation, and that the names of Stichting Mathematisch
|
|
|
12 Centrum or CWI not be used in advertising or publicity pertaining to
|
|
|
13 distribution of the software without specific, written prior permission.
|
|
|
14
|
|
|
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
|
|
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
|
|
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
|
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
22
|
|
|
23 ******************************************************************/
|
|
|
24
|
|
|
25 /* Berkeley DB interface.
|
|
|
26 Author: Michael McLay
|
|
|
27 Hacked: Guido van Rossum
|
|
|
28 Btree and Recno additions plus sequence methods: David Ely
|
|
|
29
|
|
|
30 XXX To do:
|
|
|
31 - provide interface to the B-tree and record libraries too
|
|
|
32 - provide a way to access the various hash functions
|
|
|
33 - support more open flags
|
|
|
34 */
|
|
|
35
|
|
|
36 #include "allobjects.h"
|
|
|
37 #include "modsupport.h"
|
|
|
38
|
|
|
39 #include <sys/types.h>
|
|
|
40 #include <sys/stat.h>
|
|
|
41 #include <fcntl.h>
|
|
|
42 #include <db.h>
|
|
|
43 /* Please don't include internal header files of the Berkeley db package
|
|
|
44 (it messes up the info required in the Setup file) */
|
|
|
45
|
|
|
46 typedef struct {
|
|
|
47 OB_HEAD
|
|
|
48 DB *di_bsddb;
|
|
|
49 int di_size; /* -1 means recompute */
|
|
|
50 } bsddbobject;
|
|
|
51
|
|
|
52 staticforward typeobject Bsddbtype;
|
|
|
53
|
|
|
54 #define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype)
|
|
|
55
|
|
|
56 static object *BsddbError;
|
|
|
57
|
|
|
58 static object *
|
|
|
59 newdbhashobject(file, flags, mode,
|
|
|
60 bsize, ffactor, nelem, cachesize, hash, lorder)
|
|
|
61 char *file;
|
|
|
62 int flags;
|
|
|
63 int mode;
|
|
|
64 int bsize;
|
|
|
65 int ffactor;
|
|
|
66 int nelem;
|
|
|
67 int cachesize;
|
|
|
68 int hash; /* XXX ignored */
|
|
|
69 int lorder;
|
|
|
70 {
|
|
|
71 bsddbobject *dp;
|
|
|
72 HASHINFO info;
|
|
|
73
|
|
|
74 if ((dp = NEWOBJ(bsddbobject, &Bsddbtype)) == NULL)
|
|
|
75 return NULL;
|
|
|
76
|
|
|
77 info.bsize = bsize;
|
|
|
78 info.ffactor = ffactor;
|
|
|
79 info.nelem = nelem;
|
|
|
80 info.cachesize = cachesize;
|
|
|
81 info.hash = NULL; /* XXX should derive from hash argument */
|
|
|
82 info.lorder = lorder;
|
|
|
83
|
|
|
84 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info)) == NULL) {
|
|
|
85 err_errno(BsddbError);
|
|
|
86 DECREF(dp);
|
|
|
87 return NULL;
|
|
|
88 }
|
|
|
89
|
|
|
90 dp->di_size = -1;
|
|
|
91
|
|
|
92 return (object *)dp;
|
|
|
93 }
|
|
|
94
|
|
|
95 static object *
|
|
|
96 newdbbtobject(file, flags, mode,
|
|
|
97 btflags, cachesize, maxkeypage, minkeypage, psize, lorder)
|
|
|
98 char *file;
|
|
|
99 int flags;
|
|
|
100 int mode;
|
|
|
101 int btflags;
|
|
|
102 int cachesize;
|
|
|
103 int maxkeypage;
|
|
|
104 int minkeypage;
|
|
|
105 int psize;
|
|
|
106 int lorder;
|
|
|
107 {
|
|
|
108 bsddbobject *dp;
|
|
|
109 BTREEINFO info;
|
|
|
110
|
|
|
111 if ((dp = NEWOBJ(bsddbobject, &Bsddbtype)) == NULL)
|
|
|
112 return NULL;
|
|
|
113
|
|
|
114 info.flags = btflags;
|
|
|
115 info.cachesize = cachesize;
|
|
|
116 info.maxkeypage = maxkeypage;
|
|
|
117 info.minkeypage = minkeypage;
|
|
|
118 info.psize = psize;
|
|
|
119 info.lorder = lorder;
|
|
|
120 info.compare = 0; /* Use default comparison functions, for now..*/
|
|
|
121 info.prefix = 0;
|
|
|
122
|
|
|
123 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info)) == NULL) {
|
|
|
124 err_errno(BsddbError);
|
|
|
125 DECREF(dp);
|
|
|
126 return NULL;
|
|
|
127 }
|
|
|
128
|
|
|
129 dp->di_size = -1;
|
|
|
130
|
|
|
131 return (object *)dp;
|
|
|
132 }
|
|
|
133
|
|
|
134 static object *
|
|
|
135 newdbrnobject(file, flags, mode,
|
|
|
136 rnflags, cachesize, psize, lorder, reclen, bval, bfname)
|
|
|
137 char *file;
|
|
|
138 int flags;
|
|
|
139 int mode;
|
|
|
140 int rnflags;
|
|
|
141 int cachesize;
|
|
|
142 int psize;
|
|
|
143 int lorder;
|
|
|
144 size_t reclen;
|
|
|
145 u_char bval;
|
|
|
146 char *bfname;
|
|
|
147 {
|
|
|
148 bsddbobject *dp;
|
|
|
149 RECNOINFO info;
|
|
|
150
|
|
|
151 if ((dp = NEWOBJ(bsddbobject, &Bsddbtype)) == NULL)
|
|
|
152 return NULL;
|
|
|
153
|
|
|
154 info.flags = rnflags;
|
|
|
155 info.cachesize = cachesize;
|
|
|
156 info.psize = psize;
|
|
|
157 info.lorder = lorder;
|
|
|
158 info.reclen = reclen;
|
|
|
159 info.bval = bval;
|
|
|
160 info.bfname = bfname;
|
|
|
161
|
|
|
162 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info)) == NULL) {
|
|
|
163 err_errno(BsddbError);
|
|
|
164 DECREF(dp);
|
|
|
165 return NULL;
|
|
|
166 }
|
|
|
167
|
|
|
168 dp->di_size = -1;
|
|
|
169
|
|
|
170 return (object *)dp;
|
|
|
171 }
|
|
|
172
|
|
|
173
|
|
|
174 static void
|
|
|
175 bsddb_dealloc(dp)
|
|
|
176 bsddbobject *dp;
|
|
|
177 {
|
|
|
178 if (dp->di_bsddb != NULL) {
|
|
|
179 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0)
|
|
|
180 fprintf(stderr,
|
|
|
181 "Python bsddb: close errno %s in dealloc\n", errno);
|
|
|
182 }
|
|
|
183 DEL(dp);
|
|
|
184 }
|
|
|
185
|
|
|
186 static int
|
|
|
187 bsddb_length(dp)
|
|
|
188 bsddbobject *dp;
|
|
|
189 {
|
|
|
190 if (dp->di_size < 0) {
|
|
|
191 DBT krec, drec;
|
|
|
192 int status;
|
|
|
193 int size = 0;
|
|
|
194 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec,R_FIRST);
|
|
|
195 status == 0;
|
|
|
196 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT))
|
|
|
197 size++;
|
|
|
198 if (status < 0) {
|
|
|
199 err_errno(BsddbError);
|
|
|
200 return -1;
|
|
|
201 }
|
|
|
202 dp->di_size = size;
|
|
|
203 }
|
|
|
204 return dp->di_size;
|
|
|
205 }
|
|
|
206
|
|
|
207 static object *
|
|
|
208 bsddb_subscript(dp, key)
|
|
|
209 bsddbobject *dp;
|
|
|
210 object *key;
|
|
|
211 {
|
|
|
212 int status;
|
|
|
213 object *v;
|
|
|
214 DBT krec, drec;
|
|
|
215 char *data;
|
|
|
216 int size;
|
|
|
217
|
|
|
218 if (!getargs(key, "s#", &data, &size))
|
|
|
219 return NULL;
|
|
|
220 krec.data = data;
|
|
|
221 krec.size = size;
|
|
|
222
|
|
|
223 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
|
|
|
224 if (status != 0) {
|
|
|
225 if (status < 0)
|
|
|
226 err_errno(BsddbError);
|
|
|
227 else
|
|
|
228 err_setval(KeyError, key);
|
|
|
229 return NULL;
|
|
|
230 }
|
|
|
231
|
|
|
232 return newsizedstringobject((char *)drec.data, (int)drec.size);
|
|
|
233 }
|
|
|
234
|
|
|
235 static int
|
|
|
236 bsddb_ass_sub(dp, key, value)
|
|
|
237 bsddbobject *dp;
|
|
|
238 object *key, *value;
|
|
|
239 {
|
|
|
240 int status;
|
|
|
241 DBT krec, drec;
|
|
|
242 char *data;
|
|
|
243 int size;
|
|
|
244
|
|
|
245 if (!getargs(key, "s#", &data, &size)) {
|
|
|
246 err_setstr(TypeError, "bsddb key type must be string");
|
|
|
247 return -1;
|
|
|
248 }
|
|
|
249 krec.data = data;
|
|
|
250 krec.size = size;
|
|
|
251 dp->di_size = -1;
|
|
|
252 if (value == NULL) {
|
|
|
253 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
|
|
|
254 }
|
|
|
255 else {
|
|
|
256 if (!getargs(value, "s#", &data, &size)) {
|
|
|
257 err_setstr(TypeError, "bsddb value type must be string");
|
|
|
258 return -1;
|
|
|
259 }
|
|
|
260 drec.data = data;
|
|
|
261 drec.size = size;
|
|
|
262 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
|
|
|
263 }
|
|
|
264 if (status != 0) {
|
|
|
265 if (status < 0)
|
|
|
266 err_errno(BsddbError);
|
|
|
267 else
|
|
|
268 err_setval(KeyError, key);
|
|
|
269 return -1;
|
|
|
270 }
|
|
|
271 return 0;
|
|
|
272 }
|
|
|
273
|
|
|
274 static mapping_methods bsddb_as_mapping = {
|
|
|
275 (inquiry)bsddb_length, /*mp_length*/
|
|
|
276 (binaryfunc)bsddb_subscript, /*mp_subscript*/
|
|
|
277 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
|
|
|
278 };
|
|
|
279
|
|
|
280 static object *
|
|
|
281 bsddb_close(dp, args)
|
|
|
282 bsddbobject *dp;
|
|
|
283 object *args;
|
|
|
284 {
|
|
|
285 if (!getnoarg(args))
|
|
|
286 return NULL;
|
|
|
287 if (dp->di_bsddb != NULL) {
|
|
|
288 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0) {
|
|
|
289 dp->di_bsddb = NULL;
|
|
|
290 err_errno(BsddbError);
|
|
|
291 return NULL;
|
|
|
292 }
|
|
|
293 }
|
|
|
294 dp->di_bsddb = NULL;
|
|
|
295 INCREF(None);
|
|
|
296 return None;
|
|
|
297 }
|
|
|
298
|
|
|
299 static object *
|
|
|
300 bsddb_keys(dp, args)
|
|
|
301 bsddbobject *dp;
|
|
|
302 object *args;
|
|
|
303 {
|
|
|
304 object *list, *item;
|
|
|
305 DBT krec, drec;
|
|
|
306 int status;
|
|
|
307 int err;
|
|
|
308
|
|
|
309 if (!getnoarg(args))
|
|
|
310 return NULL;
|
|
|
311 list = newlistobject(0);
|
|
|
312 if (list == NULL)
|
|
|
313 return NULL;
|
|
|
314 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
|
|
|
315 status == 0;
|
|
|
316 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT)) {
|
|
|
317 item = newsizedstringobject((char *)krec.data, (int)krec.size);
|
|
|
318 if (item == NULL) {
|
|
|
319 DECREF(list);
|
|
|
320 return NULL;
|
|
|
321 }
|
|
|
322 err = addlistitem(list, item);
|
|
|
323 DECREF(item);
|
|
|
324 if (err != 0) {
|
|
|
325 DECREF(list);
|
|
|
326 return NULL;
|
|
|
327 }
|
|
|
328 }
|
|
|
329 if (status < 0) {
|
|
|
330 err_errno(BsddbError);
|
|
|
331 DECREF(list);
|
|
|
332 return NULL;
|
|
|
333 }
|
|
|
334 if (dp->di_size < 0)
|
|
|
335 dp->di_size = getlistsize(list); /* We just did the work for this... */
|
|
|
336 return list;
|
|
|
337 }
|
|
|
338
|
|
|
339 static object *
|
|
|
340 bsddb_has_key(dp, args)
|
|
|
341 bsddbobject *dp;
|
|
|
342 object *args;
|
|
|
343 {
|
|
|
344 DBT krec, drec;
|
|
|
345 int status;
|
|
|
346 char *data;
|
|
|
347 int size;
|
|
|
348
|
|
|
349 if (!getargs(args, "s#", &data, &size))
|
|
|
350 return NULL;
|
|
|
351 krec.data = data;
|
|
|
352 krec.size = size;
|
|
|
353
|
|
|
354 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
|
|
|
355 if (status < 0) {
|
|
|
356 err_errno(BsddbError);
|
|
|
357 return NULL;
|
|
|
358 }
|
|
|
359
|
|
|
360 return newintobject(status == 0);
|
|
|
361 }
|
|
|
362
|
|
|
363 static object *
|
|
|
364 bsddb_set_location(dp, key)
|
|
|
365 bsddbobject *dp;
|
|
|
366 object *key;
|
|
|
367 {
|
|
|
368 int status;
|
|
|
369 object *v;
|
|
|
370 DBT krec, drec;
|
|
|
371 char *data;
|
|
|
372 int size;
|
|
|
373
|
|
|
374 if (!getargs(key, "s#", &data, &size))
|
|
|
375 return NULL;
|
|
|
376 krec.data = data;
|
|
|
377 krec.size = size;
|
|
|
378
|
|
|
379 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
|
|
|
380 if (status != 0) {
|
|
|
381 if (status < 0)
|
|
|
382 err_errno(BsddbError);
|
|
|
383 else
|
|
|
384 err_setval(KeyError, key);
|
|
|
385 return NULL;
|
|
|
386 }
|
|
|
387
|
|
|
388 return mkvalue("s#s#", krec.data, krec.size, drec.data, drec.size);
|
|
|
389 }
|
|
|
390
|
|
|
391 static object *
|
|
|
392 bsddb_seq(dp, args, sequence_request)
|
|
|
393 bsddbobject *dp;
|
|
|
394 object *args;
|
|
|
395 int sequence_request;
|
|
|
396 {
|
|
|
397 int status;
|
|
|
398 DBT krec, drec;
|
|
|
399
|
|
|
400 if (!getnoarg(args))
|
|
|
401 return NULL;
|
|
|
402
|
|
|
403 krec.data = 0;
|
|
|
404 krec.size = 0;
|
|
|
405
|
|
|
406 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, sequence_request);
|
|
|
407 if (status != 0) {
|
|
|
408 if (status < 0)
|
|
|
409 err_errno(BsddbError);
|
|
|
410 else
|
|
|
411 err_setval(KeyError, args);
|
|
|
412 return NULL;
|
|
|
413 }
|
|
|
414
|
|
|
415 return mkvalue("s#s#", krec.data, krec.size, drec.data, drec.size);
|
|
|
416 }
|
|
|
417
|
|
|
418 static object *
|
|
|
419 bsddb_next(dp, key)
|
|
|
420 bsddbobject *dp;
|
|
|
421 object *key;
|
|
|
422 {
|
|
|
423 return bsddb_seq(dp, key, R_NEXT);
|
|
|
424 }
|
|
|
425 static object *
|
|
|
426 bsddb_previous(dp, key)
|
|
|
427 bsddbobject *dp;
|
|
|
428 object *key;
|
|
|
429 {
|
|
|
430 return bsddb_seq(dp, key, R_PREV);
|
|
|
431 }
|
|
|
432 static object *
|
|
|
433 bsddb_first(dp, key)
|
|
|
434 bsddbobject *dp;
|
|
|
435 object *key;
|
|
|
436 {
|
|
|
437 return bsddb_seq(dp, key, R_FIRST);
|
|
|
438 }
|
|
|
439 static object *
|
|
|
440 bsddb_last(dp, key)
|
|
|
441 bsddbobject *dp;
|
|
|
442 object *key;
|
|
|
443 {
|
|
|
444 return bsddb_seq(dp, key, R_LAST);
|
|
|
445 }
|
|
|
446 static object *
|
|
|
447 bsddb_sync(dp, args)
|
|
|
448 bsddbobject *dp;
|
|
|
449 object *args;
|
|
|
450 {
|
|
|
451 int status;
|
|
|
452
|
|
|
453 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
|
|
|
454 if (status != 0) {
|
|
|
455 err_errno(BsddbError);
|
|
|
456 return NULL;
|
|
|
457 }
|
|
|
458 return newintobject(status = 0);
|
|
|
459 }
|
|
|
460 static struct methodlist bsddb_methods[] = {
|
|
|
461 {"close", (method)bsddb_close},
|
|
|
462 {"keys", (method)bsddb_keys},
|
|
|
463 {"has_key", (method)bsddb_has_key},
|
|
|
464 {"set_location", (method)bsddb_set_location},
|
|
|
465 {"next", (method)bsddb_next},
|
|
|
466 {"previous", (method)bsddb_previous},
|
|
|
467 {"first", (method)bsddb_first},
|
|
|
468 {"last", (method)bsddb_last},
|
|
|
469 {"sync", (method)bsddb_sync},
|
|
|
470 {NULL, NULL} /* sentinel */
|
|
|
471 };
|
|
|
472
|
|
|
473 static object *
|
|
|
474 bsddb_getattr(dp, name)
|
|
|
475 object *dp;
|
|
|
476 char *name;
|
|
|
477 {
|
|
|
478 return findmethod(bsddb_methods, dp, name);
|
|
|
479 }
|
|
|
480
|
|
|
481 static typeobject Bsddbtype = {
|
|
|
482 OB_HEAD_INIT(&Typetype)
|
|
|
483 0,
|
|
|
484 "bsddb",
|
|
|
485 sizeof(bsddbobject),
|
|
|
486 0,
|
|
|
487 (destructor)bsddb_dealloc, /*tp_dealloc*/
|
|
|
488 0, /*tp_print*/
|
|
|
489 (getattrfunc)bsddb_getattr, /*tp_getattr*/
|
|
|
490 0, /*tp_setattr*/
|
|
|
491 0, /*tp_compare*/
|
|
|
492 0, /*tp_repr*/
|
|
|
493 0, /*tp_as_number*/
|
|
|
494 0, /*tp_as_sequence*/
|
|
|
495 &bsddb_as_mapping, /*tp_as_mapping*/
|
|
|
496 };
|
|
|
497
|
|
|
498 static object *
|
|
|
499 bsdhashopen(self, args)
|
|
|
500 object *self;
|
|
|
501 object *args;
|
|
|
502 {
|
|
|
503 char *file;
|
|
|
504 char *flag = NULL;
|
|
|
505 int flags = O_RDONLY;
|
|
|
506 int mode = 0666;
|
|
|
507 int bsize = 0;
|
|
|
508 int ffactor = 0;
|
|
|
509 int nelem = 0;
|
|
|
510 int cachesize = 0;
|
|
|
511 int hash = 0; /* XXX currently ignored */
|
|
|
512 int lorder = 0;
|
|
|
513
|
|
|
514 if (!newgetargs(args, "s|siiiiiii",
|
|
|
515 &file, &flag, &mode,
|
|
|
516 &bsize, &ffactor, &nelem, &cachesize, &hash, &lorder))
|
|
|
517 return NULL;
|
|
|
518 if (flag != NULL) {
|
|
|
519 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
|
|
|
520 if (flag[0] == 'r')
|
|
|
521 flags = O_RDONLY;
|
|
|
522 else if (flag[0] == 'w')
|
|
|
523 flags = O_RDWR;
|
|
|
524 else if (flag[0] == 'c')
|
|
|
525 flags = O_RDWR|O_CREAT;
|
|
|
526 else if (flag[0] == 'n')
|
|
|
527 flags = O_RDWR|O_CREAT|O_TRUNC;
|
|
|
528 else {
|
|
|
529 err_setstr(BsddbError,
|
|
|
530 "Flag should begin with 'r', 'w', 'c' or 'n'");
|
|
|
531 return NULL;
|
|
|
532 }
|
|
|
533 if (flag[1] == 'l') {
|
|
|
534 #if defined(O_EXLOCK) && defined(O_SHLOCK)
|
|
|
535 if (flag[0] == 'r')
|
|
|
536 flags |= O_SHLOCK;
|
|
|
537 else
|
|
|
538 flags |= O_EXLOCK;
|
|
|
539 #else
|
|
|
540 err_setstr(BsddbError, "locking not supported on this platform");
|
|
|
541 return NULL;
|
|
|
542 #endif
|
|
|
543 }
|
|
|
544 }
|
|
|
545 return newdbhashobject(file, flags, mode,
|
|
|
546 bsize, ffactor, nelem, cachesize, hash, lorder);
|
|
|
547 }
|
|
|
548
|
|
|
549 static object *
|
|
|
550 bsdbtopen(self, args)
|
|
|
551 object *self;
|
|
|
552 object *args;
|
|
|
553 {
|
|
|
554 char *file;
|
|
|
555 char *flag = NULL;
|
|
|
556 int flags = O_RDONLY;
|
|
|
557 int mode = 0666;
|
|
|
558 int cachesize = 0;
|
|
|
559 int maxkeypage;
|
|
|
560 int minkeypage;
|
|
|
561 int btflags;
|
|
|
562 unsigned int psize;
|
|
|
563 int lorder;
|
|
|
564
|
|
|
565 if (!newgetargs(args, "s|siiiiiii",
|
|
|
566 &file, &flag, &mode,
|
|
|
567 &btflags, &cachesize, &maxkeypage, &minkeypage, &psize, &lorder))
|
|
|
568 return NULL;
|
|
|
569 if (flag != NULL) {
|
|
|
570 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
|
|
|
571 if (flag[0] == 'r')
|
|
|
572 flags = O_RDONLY;
|
|
|
573 else if (flag[0] == 'w')
|
|
|
574 flags = O_RDWR;
|
|
|
575 else if (flag[0] == 'c')
|
|
|
576 flags = O_RDWR|O_CREAT;
|
|
|
577 else if (flag[0] == 'n')
|
|
|
578 flags = O_RDWR|O_CREAT|O_TRUNC;
|
|
|
579 else {
|
|
|
580 err_setstr(BsddbError,
|
|
|
581 "Flag should begin with 'r', 'w', 'c' or 'n'");
|
|
|
582 return NULL;
|
|
|
583 }
|
|
|
584 if (flag[1] == 'l') {
|
|
|
585 #if defined(O_EXLOCK) && defined(O_SHLOCK)
|
|
|
586 if (flag[0] == 'r')
|
|
|
587 flags |= O_SHLOCK;
|
|
|
588 else
|
|
|
589 flags |= O_EXLOCK;
|
|
|
590 #else
|
|
|
591 err_setstr(BsddbError, "locking not supported on this platform");
|
|
|
592 return NULL;
|
|
|
593 #endif
|
|
|
594 }
|
|
|
595 }
|
|
|
596 return newdbbtobject(file, flags, mode,
|
|
|
597 btflags, cachesize, maxkeypage, minkeypage, psize, lorder);
|
|
|
598 }
|
|
|
599 static object *
|
|
|
600 bsdrnopen(self, args)
|
|
|
601 object *self;
|
|
|
602 object *args;
|
|
|
603 {
|
|
|
604 char *file;
|
|
|
605 char *flag = NULL;
|
|
|
606 int flags = O_RDONLY;
|
|
|
607 int mode = 0666;
|
|
|
608 int cachesize = 0;
|
|
|
609 int rnflags;
|
|
|
610 unsigned int psize;
|
|
|
611 int lorder;
|
|
|
612 size_t reclen;
|
|
|
613 char *bval;
|
|
|
614 char *bfname;
|
|
|
615
|
|
|
616 if (!newgetargs(args, "s|siiiiiiss",
|
|
|
617 &file, &flag, &mode,
|
|
|
618 &rnflags, &cachesize, &psize, &lorder, &reclen, &bval, &bfname))
|
|
|
619 return NULL;
|
|
|
620 if (flag != NULL) {
|
|
|
621 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
|
|
|
622 if (flag[0] == 'r')
|
|
|
623 flags = O_RDONLY;
|
|
|
624 else if (flag[0] == 'w')
|
|
|
625 flags = O_RDWR;
|
|
|
626 else if (flag[0] == 'c')
|
|
|
627 flags = O_RDWR|O_CREAT;
|
|
|
628 else if (flag[0] == 'n')
|
|
|
629 flags = O_RDWR|O_CREAT|O_TRUNC;
|
|
|
630 else {
|
|
|
631 err_setstr(BsddbError,
|
|
|
632 "Flag should begin with 'r', 'w', 'c' or 'n'");
|
|
|
633 return NULL;
|
|
|
634 }
|
|
|
635 if (flag[1] == 'l') {
|
|
|
636 #if defined(O_EXLOCK) && defined(O_SHLOCK)
|
|
|
637 if (flag[0] == 'r')
|
|
|
638 flags |= O_SHLOCK;
|
|
|
639 else
|
|
|
640 flags |= O_EXLOCK;
|
|
|
641 #else
|
|
|
642 err_setstr(BsddbError, "locking not supported on this platform");
|
|
|
643 return NULL;
|
|
|
644 #endif
|
|
|
645 }
|
|
|
646 }
|
|
|
647 return newdbrnobject(file, flags, mode,
|
|
|
648 rnflags, cachesize, psize, lorder, bval[0], bfname);
|
|
|
649 }
|
|
|
650
|
|
|
651 static struct methodlist bsddbmodule_methods[] = {
|
|
|
652 {"hashopen", (method)bsdhashopen, 1},
|
|
|
653 {"btopen", (method)bsdbtopen, 1},
|
|
|
654 {"rnopen", (method)bsdrnopen, 1},
|
|
|
655 {0, 0},
|
|
|
656 };
|
|
|
657
|
|
|
658 void
|
|
|
659 initbsddb() {
|
|
|
660 object *m, *d;
|
|
|
661
|
|
|
662 m = initmodule("bsddb", bsddbmodule_methods);
|
|
|
663 d = getmoduledict(m);
|
|
|
664 BsddbError = newstringobject("bsddb.error");
|
|
|
665 if (BsddbError == NULL || dictinsert(d, "error", BsddbError))
|
|
|
666 fatal("can't define bsddb.error");
|
|
|
667 }
|