1 /* Berkeley DB interface. 2 Author: Michael McLay 3 Hacked: Guido van Rossum 4 Btree and Recno additions plus sequence methods: David Ely 5 Hacked by Gustavo Niemeyer <niemeyer (at) conectiva.com> fixing recno 6 support. 7 8 XXX To do: 9 - provide a way to access the various hash functions 10 - support more open flags 11 12 The windows port of the Berkeley DB code is hard to find on the web: 13 www.nightmare.com/software.html 14 */ 15 16 #include "Python.h" 17 #ifdef WITH_THREAD 18 #include "pythread.h" 19 #endif 20 21 #include <sys/types.h> 22 #include <sys/stat.h> 23 #include <fcntl.h> 24 #ifdef HAVE_DB_185_H 25 #include <db_185.h> 26 #else 27 #include <db.h> 28 #endif 29 /* Please don't include internal header files of the Berkeley db package 30 (it messes up the info required in the Setup file) */ 31 32 typedef struct { 33 PyObject_HEAD 34 DB *di_bsddb; 35 int di_size; /* -1 means recompute */ 36 int di_type; 37 #ifdef WITH_THREAD 38 PyThread_type_lock di_lock; 39 #endif 40 } bsddbobject; 41 42 static PyTypeObject Bsddbtype; 43 44 #define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype) 45 #define check_bsddbobject_open(v, r) if ((v)->di_bsddb == NULL) \ 46 { PyErr_SetString(BsddbError, \ 47 "BSDDB object has already been closed"); \ 48 return r; } 49 50 static PyObject *BsddbError; 51 52 static PyObject * 53 newdbhashobject(char *file, int flags, int mode, 54 int bsize, int ffactor, int nelem, int cachesize, 55 int hash, int lorder) 56 { 57 bsddbobject *dp; 58 HASHINFO info; 59 60 if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL) 61 return NULL; 62 63 info.bsize = bsize; 64 info.ffactor = ffactor; 65 info.nelem = nelem; 66 info.cachesize = cachesize; 67 info.hash = NULL; /* XXX should derive from hash argument */ 68 info.lorder = lorder; 69 70 #ifdef O_BINARY 71 flags |= O_BINARY; 72 #endif 73 Py_BEGIN_ALLOW_THREADS 74 dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info); 75 Py_END_ALLOW_THREADS 76 if (dp->di_bsddb == NULL) { 77 PyErr_SetFromErrno(BsddbError); 78 #ifdef WITH_THREAD 79 dp->di_lock = NULL; 80 #endif 81 Py_DECREF(dp); 82 return NULL; 83 } 84 85 dp->di_size = -1; 86 dp->di_type = DB_HASH; 87 88 #ifdef WITH_THREAD 89 dp->di_lock = PyThread_allocate_lock(); 90 if (dp->di_lock == NULL) { 91 PyErr_SetString(BsddbError, "can't allocate lock"); 92 Py_DECREF(dp); 93 return NULL; 94 } 95 #endif 96 97 return (PyObject *)dp; 98 } 99 100 static PyObject * 101 newdbbtobject(char *file, int flags, int mode, 102 int btflags, int cachesize, int maxkeypage, 103 int minkeypage, int psize, int lorder) 104 { 105 bsddbobject *dp; 106 BTREEINFO info; 107 108 if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL) 109 return NULL; 110 111 info.flags = btflags; 112 info.cachesize = cachesize; 113 info.maxkeypage = maxkeypage; 114 info.minkeypage = minkeypage; 115 info.psize = psize; 116 info.lorder = lorder; 117 info.compare = 0; /* Use default comparison functions, for now..*/ 118 info.prefix = 0; 119 120 #ifdef O_BINARY 121 flags |= O_BINARY; 122 #endif 123 Py_BEGIN_ALLOW_THREADS 124 dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info); 125 Py_END_ALLOW_THREADS 126 if (dp->di_bsddb == NULL) { 127 PyErr_SetFromErrno(BsddbError); 128 #ifdef WITH_THREAD 129 dp->di_lock = NULL; 130 #endif 131 Py_DECREF(dp); 132 return NULL; 133 } 134 135 dp->di_size = -1; 136 dp->di_type = DB_BTREE; 137 138 #ifdef WITH_THREAD 139 dp->di_lock = PyThread_allocate_lock(); 140 if (dp->di_lock == NULL) { 141 PyErr_SetString(BsddbError, "can't allocate lock"); 142 Py_DECREF(dp); 143 return NULL; 144 } 145 #endif 146 147 return (PyObject *)dp; 148 } 149 150 static PyObject * 151 newdbrnobject(char *file, int flags, int mode, 152 int rnflags, int cachesize, int psize, int lorder, 153 size_t reclen, u_char bval, char *bfname) 154 { 155 bsddbobject *dp; 156 RECNOINFO info; 157 int fd; 158 159 if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL) 160 return NULL; 161 162 info.flags = rnflags; 163 info.cachesize = cachesize; 164 info.psize = psize; 165 info.lorder = lorder; 166 info.reclen = reclen; 167 info.bval = bval; 168 info.bfname = bfname; 169 170 #ifdef O_BINARY 171 flags |= O_BINARY; 172 #endif 173 /* This is a hack to avoid a dbopen() bug that happens when 174 * it fails. */ 175 fd = open(file, flags); 176 if (fd == -1) { 177 dp->di_bsddb = NULL; 178 } 179 else { 180 close(fd); 181 Py_BEGIN_ALLOW_THREADS 182 dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info); 183 Py_END_ALLOW_THREADS 184 } 185 if (dp->di_bsddb == NULL) { 186 PyErr_SetFromErrno(BsddbError); 187 #ifdef WITH_THREAD 188 dp->di_lock = NULL; 189 #endif 190 Py_DECREF(dp); 191 return NULL; 192 } 193 194 dp->di_size = -1; 195 dp->di_type = DB_RECNO; 196 197 #ifdef WITH_THREAD 198 dp->di_lock = PyThread_allocate_lock(); 199 if (dp->di_lock == NULL) { 200 PyErr_SetString(BsddbError, "can't allocate lock"); 201 Py_DECREF(dp); 202 return NULL; 203 } 204 #endif 205 206 return (PyObject *)dp; 207 } 208 209 static void 210 bsddb_dealloc(bsddbobject *dp) 211 { 212 #ifdef WITH_THREAD 213 if (dp->di_lock) { 214 PyThread_acquire_lock(dp->di_lock, 0); 215 PyThread_release_lock(dp->di_lock); 216 PyThread_free_lock(dp->di_lock); 217 dp->di_lock = NULL; 218 } 219 #endif 220 if (dp->di_bsddb != NULL) { 221 int status; 222 Py_BEGIN_ALLOW_THREADS 223 status = (dp->di_bsddb->close)(dp->di_bsddb); 224 Py_END_ALLOW_THREADS 225 if (status != 0) 226 fprintf(stderr, 227 "Python bsddb: close errno %d in dealloc\n", 228 errno); 229 } 230 PyObject_Del(dp); 231 } 232 233 #ifdef WITH_THREAD 234 #define BSDDB_BGN_SAVE(_dp) \ 235 Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(_dp->di_lock,1); 236 #define BSDDB_END_SAVE(_dp) \ 237 PyThread_release_lock(_dp->di_lock); Py_END_ALLOW_THREADS 238 #else 239 #define BSDDB_BGN_SAVE(_dp) Py_BEGIN_ALLOW_THREADS 240 #define BSDDB_END_SAVE(_dp) Py_END_ALLOW_THREADS 241 #endif 242 243 static Py_ssize_t 244 bsddb_length(bsddbobject *dp) 245 { 246 check_bsddbobject_open(dp, -1); 247 if (dp->di_size < 0) { 248 DBT krec, drec; 249 int status; 250 int size = 0; 251 BSDDB_BGN_SAVE(dp) 252 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, 253 &krec, &drec,R_FIRST); 254 status == 0; 255 status = (dp->di_bsddb->seq)(dp->di_bsddb, 256 &krec, &drec, R_NEXT)) 257 size++; 258 BSDDB_END_SAVE(dp) 259 if (status < 0) { 260 PyErr_SetFromErrno(BsddbError); 261 return -1; 262 } 263 dp->di_size = size; 264 } 265 return dp->di_size; 266 } 267 268 static PyObject * 269 bsddb_subscript(bsddbobject *dp, PyObject *key) 270 { 271 int status; 272 DBT krec, drec; 273 char *data = NULL; 274 char buf[4096]; 275 int size; 276 PyObject *result; 277 recno_t recno; 278 279 if (dp->di_type == DB_RECNO) { 280 if (!PyArg_Parse(key, "i", &recno)) { 281 PyErr_SetString(PyExc_TypeError, 282 "key type must be integer"); 283 return NULL; 284 } 285 krec.data = &recno; 286 krec.size = sizeof(recno); 287 } 288 else { 289 if (!PyArg_Parse(key, "s#", &data, &size)) { 290 PyErr_SetString(PyExc_TypeError, 291 "key type must be string"); 292 return NULL; 293 } 294 krec.data = data; 295 krec.size = size; 296 } 297 check_bsddbobject_open(dp, NULL); 298 299 BSDDB_BGN_SAVE(dp) 300 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0); 301 if (status == 0) { 302 if (drec.size > sizeof(buf)) data = malloc(drec.size); 303 else data = buf; 304 if (data!=NULL) memcpy(data,drec.data,drec.size); 305 } 306 BSDDB_END_SAVE(dp) 307 if (data==NULL) return PyErr_NoMemory(); 308 if (status != 0) { 309 if (status < 0) 310 PyErr_SetFromErrno(BsddbError); 311 else 312 PyErr_SetObject(PyExc_KeyError, key); 313 return NULL; 314 } 315 316 result = PyString_FromStringAndSize(data, (int)drec.size); 317 if (data != buf) free(data); 318 return result; 319 } 320 321 static int 322 bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value) 323 { 324 int status; 325 DBT krec, drec; 326 char *data; 327 int size; 328 recno_t recno; 329 330 if (dp->di_type == DB_RECNO) { 331 if (!PyArg_Parse(key, "i", &recno)) { 332 PyErr_SetString(PyExc_TypeError, 333 "bsddb key type must be integer"); 334 return -1; 335 } 336 krec.data = &recno; 337 krec.size = sizeof(recno); 338 } 339 else { 340 if (!PyArg_Parse(key, "s#", &data, &size)) { 341 PyErr_SetString(PyExc_TypeError, 342 "bsddb key type must be string"); 343 return -1; 344 } 345 krec.data = data; 346 krec.size = size; 347 } 348 check_bsddbobject_open(dp, -1); 349 dp->di_size = -1; 350 if (value == NULL) { 351 BSDDB_BGN_SAVE(dp) 352 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0); 353 BSDDB_END_SAVE(dp) 354 } 355 else { 356 if (!PyArg_Parse(value, "s#", &data, &size)) { 357 PyErr_SetString(PyExc_TypeError, 358 "bsddb value type must be string"); 359 return -1; 360 } 361 drec.data = data; 362 drec.size = size; 363 BSDDB_BGN_SAVE(dp) 364 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0); 365 BSDDB_END_SAVE(dp) 366 } 367 if (status != 0) { 368 if (status < 0) 369 PyErr_SetFromErrno(BsddbError); 370 else 371 PyErr_SetObject(PyExc_KeyError, key); 372 return -1; 373 } 374 return 0; 375 } 376 377 static PyMappingMethods bsddb_as_mapping = { 378 (lenfunc)bsddb_length, /*mp_length*/ 379 (binaryfunc)bsddb_subscript, /*mp_subscript*/ 380 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/ 381 }; 382 383 static PyObject * 384 bsddb_close(bsddbobject *dp) 385 { 386 if (dp->di_bsddb != NULL) { 387 int status; 388 BSDDB_BGN_SAVE(dp) 389 status = (dp->di_bsddb->close)(dp->di_bsddb); 390 BSDDB_END_SAVE(dp) 391 if (status != 0) { 392 dp->di_bsddb = NULL; 393 PyErr_SetFromErrno(BsddbError); 394 return NULL; 395 } 396 } 397 dp->di_bsddb = NULL; 398 Py_INCREF(Py_None); 399 return Py_None; 400 } 401 402 static PyObject * 403 bsddb_keys(bsddbobject *dp) 404 { 405 PyObject *list, *item=NULL; 406 DBT krec, drec; 407 char *data=NULL,buf[4096]; 408 int status; 409 int err; 410 411 check_bsddbobject_open(dp, NULL); 412 list = PyList_New(0); 413 if (list == NULL) 414 return NULL; 415 BSDDB_BGN_SAVE(dp) 416 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST); 417 if (status == 0) { 418 if (krec.size > sizeof(buf)) data = malloc(krec.size); 419 else data = buf; 420 if (data != NULL) memcpy(data,krec.data,krec.size); 421 } 422 BSDDB_END_SAVE(dp) 423 if (status == 0 && data==NULL) return PyErr_NoMemory(); 424 while (status == 0) { 425 if (dp->di_type == DB_RECNO) 426 item = PyInt_FromLong(*((int*)data)); 427 else 428 item = PyString_FromStringAndSize(data, 429 (int)krec.size); 430 if (data != buf) free(data); 431 if (item == NULL) { 432 Py_DECREF(list); 433 return NULL; 434 } 435 err = PyList_Append(list, item); 436 Py_DECREF(item); 437 if (err != 0) { 438 Py_DECREF(list); 439 return NULL; 440 } 441 BSDDB_BGN_SAVE(dp) 442 status = (dp->di_bsddb->seq) 443 (dp->di_bsddb, &krec, &drec, R_NEXT); 444 if (status == 0) { 445 if (krec.size > sizeof(buf)) 446 data = malloc(krec.size); 447 else data = buf; 448 if (data != NULL) 449 memcpy(data,krec.data,krec.size); 450 } 451 BSDDB_END_SAVE(dp) 452 if (data == NULL) return PyErr_NoMemory(); 453 } 454 if (status < 0) { 455 PyErr_SetFromErrno(BsddbError); 456 Py_DECREF(list); 457 return NULL; 458 } 459 if (dp->di_size < 0) 460 dp->di_size = PyList_Size(list); /* We just did the work */ 461 return list; 462 } 463 464 static PyObject * 465 bsddb_has_key(bsddbobject *dp, PyObject *args) 466 { 467 DBT krec, drec; 468 int status; 469 char *data; 470 int size; 471 recno_t recno; 472 473 if (dp->di_type == DB_RECNO) { 474 if (!PyArg_ParseTuple(args, "i;key type must be integer", 475 &recno)) { 476 return NULL; 477 } 478 krec.data = &recno; 479 krec.size = sizeof(recno); 480 } 481 else { 482 if (!PyArg_ParseTuple(args, "s#;key type must be string", 483 &data, &size)) { 484 return NULL; 485 } 486 krec.data = data; 487 krec.size = size; 488 } 489 check_bsddbobject_open(dp, NULL); 490 491 BSDDB_BGN_SAVE(dp) 492 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0); 493 BSDDB_END_SAVE(dp) 494 if (status < 0) { 495 PyErr_SetFromErrno(BsddbError); 496 return NULL; 497 } 498 499 return PyInt_FromLong(status == 0); 500 } 501 502 static PyObject * 503 bsddb_set_location(bsddbobject *dp, PyObject *key) 504 { 505 int status; 506 DBT krec, drec; 507 char *data = NULL; 508 char buf[4096]; 509 int size; 510 PyObject *result; 511 recno_t recno; 512 513 if (dp->di_type == DB_RECNO) { 514 if (!PyArg_ParseTuple(key, "i;key type must be integer", 515 &recno)) { 516 return NULL; 517 } 518 krec.data = &recno; 519 krec.size = sizeof(recno); 520 } 521 else { 522 if (!PyArg_ParseTuple(key, "s#;key type must be string", 523 &data, &size)) { 524 return NULL; 525 } 526 krec.data = data; 527 krec.size = size; 528 } 529 check_bsddbobject_open(dp, NULL); 530 531 BSDDB_BGN_SAVE(dp) 532 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR); 533 if (status == 0) { 534 if (drec.size > sizeof(buf)) data = malloc(drec.size); 535 else data = buf; 536 if (data!=NULL) memcpy(data,drec.data,drec.size); 537 } 538 BSDDB_END_SAVE(dp) 539 if (data==NULL) return PyErr_NoMemory(); 540 if (status != 0) { 541 if (status < 0) 542 PyErr_SetFromErrno(BsddbError); 543 else 544 PyErr_SetObject(PyExc_KeyError, key); 545 return NULL; 546 } 547 548 if (dp->di_type == DB_RECNO) 549 result = Py_BuildValue("is#", *((int*)krec.data), 550 data, drec.size); 551 else 552 result = Py_BuildValue("s#s#", krec.data, krec.size, 553 data, drec.size); 554 if (data != buf) free(data); 555 return result; 556 } 557 558 static PyObject * 559 bsddb_seq(bsddbobject *dp, int sequence_request) 560 { 561 int status; 562 DBT krec, drec; 563 char *kdata=NULL,kbuf[4096]; 564 char *ddata=NULL,dbuf[4096]; 565 PyObject *result; 566 567 check_bsddbobject_open(dp, NULL); 568 krec.data = 0; 569 krec.size = 0; 570 571 BSDDB_BGN_SAVE(dp) 572 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, 573 &drec, sequence_request); 574 if (status == 0) { 575 if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size); 576 else kdata = kbuf; 577 if (kdata != NULL) memcpy(kdata,krec.data,krec.size); 578 if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size); 579 else ddata = dbuf; 580 if (ddata != NULL) memcpy(ddata,drec.data,drec.size); 581 } 582 BSDDB_END_SAVE(dp) 583 if (status == 0) { 584 if ((kdata == NULL) || (ddata == NULL)) 585 return PyErr_NoMemory(); 586 } 587 else { 588 /* (status != 0) */ 589 if (status < 0) 590 PyErr_SetFromErrno(BsddbError); 591 else 592 PyErr_SetString(PyExc_KeyError, "no key/data pairs"); 593 return NULL; 594 } 595 596 if (dp->di_type == DB_RECNO) 597 result = Py_BuildValue("is#", *((int*)kdata), 598 ddata, drec.size); 599 else 600 result = Py_BuildValue("s#s#", kdata, krec.size, 601 ddata, drec.size); 602 if (kdata != kbuf) free(kdata); 603 if (ddata != dbuf) free(ddata); 604 return result; 605 } 606 607 static PyObject * 608 bsddb_next(bsddbobject *dp) 609 { 610 return bsddb_seq(dp, R_NEXT); 611 } 612 static PyObject * 613 bsddb_previous(bsddbobject *dp) 614 { 615 return bsddb_seq(dp, R_PREV); 616 } 617 static PyObject * 618 bsddb_first(bsddbobject *dp) 619 { 620 return bsddb_seq(dp, R_FIRST); 621 } 622 static PyObject * 623 bsddb_last(bsddbobject *dp) 624 { 625 return bsddb_seq(dp, R_LAST); 626 } 627 static PyObject * 628 bsddb_sync(bsddbobject *dp) 629 { 630 int status; 631 632 check_bsddbobject_open(dp, NULL); 633 BSDDB_BGN_SAVE(dp) 634 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0); 635 BSDDB_END_SAVE(dp) 636 if (status != 0) { 637 PyErr_SetFromErrno(BsddbError); 638 return NULL; 639 } 640 return PyInt_FromLong(0); 641 } 642 static PyMethodDef bsddb_methods[] = { 643 {"close", (PyCFunction)bsddb_close, METH_NOARGS}, 644 {"keys", (PyCFunction)bsddb_keys, METH_NOARGS}, 645 {"has_key", (PyCFunction)bsddb_has_key, METH_VARARGS}, 646 {"set_location", (PyCFunction)bsddb_set_location, METH_VARARGS}, 647 {"next", (PyCFunction)bsddb_next, METH_NOARGS}, 648 {"previous", (PyCFunction)bsddb_previous, METH_NOARGS}, 649 {"first", (PyCFunction)bsddb_first, METH_NOARGS}, 650 {"last", (PyCFunction)bsddb_last, METH_NOARGS}, 651 {"sync", (PyCFunction)bsddb_sync, METH_NOARGS}, 652 {NULL, NULL} /* sentinel */ 653 }; 654 655 static PyObject * 656 bsddb_getattr(PyObject *dp, char *name) 657 { 658 return Py_FindMethod(bsddb_methods, dp, name); 659 } 660 661 static PyTypeObject Bsddbtype = { 662 PyObject_HEAD_INIT(NULL) 663 0, 664 "bsddb.bsddb", 665 sizeof(bsddbobject), 666 0, 667 (destructor)bsddb_dealloc, /*tp_dealloc*/ 668 0, /*tp_print*/ 669 (getattrfunc)bsddb_getattr, /*tp_getattr*/ 670 0, /*tp_setattr*/ 671 0, /*tp_compare*/ 672 0, /*tp_repr*/ 673 0, /*tp_as_number*/ 674 0, /*tp_as_sequence*/ 675 &bsddb_as_mapping, /*tp_as_mapping*/ 676 }; 677 678 static PyObject * 679 bsdhashopen(PyObject *self, PyObject *args) 680 { 681 char *file; 682 char *flag = NULL; 683 int flags = O_RDONLY; 684 int mode = 0666; 685 int bsize = 0; 686 int ffactor = 0; 687 int nelem = 0; 688 int cachesize = 0; 689 int hash = 0; /* XXX currently ignored */ 690 int lorder = 0; 691 692 if (!PyArg_ParseTuple(args, "z|siiiiiii:hashopen", 693 &file, &flag, &mode, 694 &bsize, &ffactor, &nelem, &cachesize, 695 &hash, &lorder)) 696 return NULL; 697 if (flag != NULL) { 698 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */ 699 if (flag[0] == 'r') 700 flags = O_RDONLY; 701 else if (flag[0] == 'w') 702 flags = O_RDWR; 703 else if (flag[0] == 'c') 704 flags = O_RDWR|O_CREAT; 705 else if (flag[0] == 'n') 706 flags = O_RDWR|O_CREAT|O_TRUNC; 707 else { 708 PyErr_SetString(BsddbError, 709 "Flag should begin with 'r', 'w', 'c' or 'n'"); 710 return NULL; 711 } 712 if (flag[1] == 'l') { 713 #if defined(O_EXLOCK) && defined(O_SHLOCK) 714 if (flag[0] == 'r') 715 flags |= O_SHLOCK; 716 else 717 flags |= O_EXLOCK; 718 #else 719 PyErr_SetString(BsddbError, 720 "locking not supported on this platform"); 721 return NULL; 722 #endif 723 } 724 } 725 return newdbhashobject(file, flags, mode, 726 bsize, ffactor, nelem, cachesize, hash, lorder); 727 } 728 729 static PyObject * 730 bsdbtopen(PyObject *self, PyObject *args) 731 { 732 char *file; 733 char *flag = NULL; 734 int flags = O_RDONLY; 735 int mode = 0666; 736 int cachesize = 0; 737 int maxkeypage = 0; 738 int minkeypage = 0; 739 int btflags = 0; 740 unsigned int psize = 0; 741 int lorder = 0; 742 743 if (!PyArg_ParseTuple(args, "z|siiiiiii:btopen", 744 &file, &flag, &mode, 745 &btflags, &cachesize, &maxkeypage, &minkeypage, 746 &psize, &lorder)) 747 return NULL; 748 if (flag != NULL) { 749 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */ 750 if (flag[0] == 'r') 751 flags = O_RDONLY; 752 else if (flag[0] == 'w') 753 flags = O_RDWR; 754 else if (flag[0] == 'c') 755 flags = O_RDWR|O_CREAT; 756 else if (flag[0] == 'n') 757 flags = O_RDWR|O_CREAT|O_TRUNC; 758 else { 759 PyErr_SetString(BsddbError, 760 "Flag should begin with 'r', 'w', 'c' or 'n'"); 761 return NULL; 762 } 763 if (flag[1] == 'l') { 764 #if defined(O_EXLOCK) && defined(O_SHLOCK) 765 if (flag[0] == 'r') 766 flags |= O_SHLOCK; 767 else 768 flags |= O_EXLOCK; 769 #else 770 PyErr_SetString(BsddbError, 771 "locking not supported on this platform"); 772 return NULL; 773 #endif 774 } 775 } 776 return newdbbtobject(file, flags, mode, 777 btflags, cachesize, maxkeypage, minkeypage, 778 psize, lorder); 779 } 780 781 static PyObject * 782 bsdrnopen(PyObject *self, PyObject *args) 783 { 784 char *file; 785 char *flag = NULL; 786 int flags = O_RDONLY; 787 int mode = 0666; 788 int cachesize = 0; 789 int rnflags = 0; 790 unsigned int psize = 0; 791 int lorder = 0; 792 size_t reclen = 0; 793 char *bval = ""; 794 char *bfname = NULL; 795 796 if (!PyArg_ParseTuple(args, "z|siiiiiiss:rnopen", 797 &file, &flag, &mode, 798 &rnflags, &cachesize, &psize, &lorder, 799 &reclen, &bval, &bfname)) 800 return NULL; 801 802 if (flag != NULL) { 803 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */ 804 if (flag[0] == 'r') 805 flags = O_RDONLY; 806 else if (flag[0] == 'w') 807 flags = O_RDWR; 808 else if (flag[0] == 'c') 809 flags = O_RDWR|O_CREAT; 810 else if (flag[0] == 'n') 811 flags = O_RDWR|O_CREAT|O_TRUNC; 812 else { 813 PyErr_SetString(BsddbError, 814 "Flag should begin with 'r', 'w', 'c' or 'n'"); 815 return NULL; 816 } 817 if (flag[1] == 'l') { 818 #if defined(O_EXLOCK) && defined(O_SHLOCK) 819 if (flag[0] == 'r') 820 flags |= O_SHLOCK; 821 else 822 flags |= O_EXLOCK; 823 #else 824 PyErr_SetString(BsddbError, 825 "locking not supported on this platform"); 826 return NULL; 827 #endif 828 } 829 else if (flag[1] != '\0') { 830 PyErr_SetString(BsddbError, 831 "Flag char 2 should be 'l' or absent"); 832 return NULL; 833 } 834 } 835 return newdbrnobject(file, flags, mode, rnflags, cachesize, 836 psize, lorder, reclen, bval[0], bfname); 837 } 838 839 static PyMethodDef bsddbmodule_methods[] = { 840 {"hashopen", (PyCFunction)bsdhashopen, METH_VARARGS}, 841 {"btopen", (PyCFunction)bsdbtopen, METH_VARARGS}, 842 {"rnopen", (PyCFunction)bsdrnopen, METH_VARARGS}, 843 /* strictly for use by dbhhash!!! */ 844 {"open", (PyCFunction)bsdhashopen, METH_VARARGS}, 845 {0, 0}, 846 }; 847 848 PyMODINIT_FUNC 849 initbsddb185(void) { 850 PyObject *m, *d; 851 852 if (PyErr_WarnPy3k("the bsddb185 module has been removed in " 853 "Python 3.0", 2) < 0) 854 return; 855 856 Bsddbtype.ob_type = &PyType_Type; 857 m = Py_InitModule("bsddb185", bsddbmodule_methods); 858 if (m == NULL) 859 return; 860 d = PyModule_GetDict(m); 861 BsddbError = PyErr_NewException("bsddb.error", NULL, NULL); 862 if (BsddbError != NULL) 863 PyDict_SetItemString(d, "error", BsddbError); 864 } 865