00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "includes.h"
00026
00027
00028
00029
00030 #ifdef HAVE_FSTAT
00031 #undef HAVE_FSTAT
00032 #endif
00033
00034 #include "Python.h"
00035
00036
00037
00038 PyObject *py_tdb_error;
00039
00040
00041
00042 typedef struct {
00043 PyObject_HEAD
00044 TDB_CONTEXT *tdb;
00045 } tdb_hnd_object;
00046
00047 PyTypeObject tdb_hnd_type;
00048
00049 PyObject *new_tdb_hnd_object(TDB_CONTEXT *tdb)
00050 {
00051 tdb_hnd_object *obj;
00052
00053 obj = PyObject_New(tdb_hnd_object, &tdb_hnd_type);
00054 obj->tdb = tdb;
00055
00056 return (PyObject *)obj;
00057 }
00058
00059 PyObject *py_tdb_close(PyObject *self, PyObject *args)
00060 {
00061 tdb_hnd_object *obj;
00062
00063 if (!PyArg_ParseTuple(args, "O!", &tdb_hnd_type, &obj))
00064 return NULL;
00065
00066 if (tdb_close(obj->tdb) == -1) {
00067 obj->tdb = NULL;
00068 PyErr_SetString(py_tdb_error, strerror(errno));
00069 return NULL;
00070 }
00071
00072 obj->tdb = NULL;
00073
00074 Py_INCREF(Py_None);
00075 return Py_None;
00076 }
00077
00078 PyObject *py_tdb_open(PyObject *self, PyObject *args, PyObject *kw)
00079 {
00080 static char *kwlist[] = { "name", "hash_size", "tdb_flags",
00081 "open_flags", "mode", NULL };
00082 char *name;
00083 int hash_size = 0, flags = TDB_DEFAULT, open_flags = -1, open_mode = 0600;
00084 TDB_CONTEXT *tdb;
00085
00086 if (!PyArg_ParseTupleAndKeywords(
00087 args, kw, "s|iiii", kwlist, &name, &hash_size, &flags,
00088 &open_flags, &open_mode))
00089 return NULL;
00090
00091
00092
00093 if (open_flags == -1) {
00094 if (access(name, W_OK) == -1)
00095 open_flags = O_RDONLY;
00096 else
00097 open_flags = O_RDWR;
00098 }
00099
00100 if (!(tdb = tdb_open(name, hash_size, flags, open_flags, open_mode))) {
00101 PyErr_SetString(py_tdb_error, strerror(errno));
00102 return NULL;
00103 }
00104
00105 return new_tdb_hnd_object(tdb);
00106 }
00107
00108
00109
00110
00111
00112 static int tdb_traverse_count(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
00113 void *state)
00114 {
00115
00116
00117
00118 return 0;
00119 }
00120
00121 static int tdb_hnd_length(tdb_hnd_object *obj)
00122 {
00123 int result;
00124
00125 result = tdb_traverse(obj->tdb, tdb_traverse_count, NULL);
00126
00127 return result;
00128 }
00129
00130 static PyObject *tdb_hnd_subscript(tdb_hnd_object *obj, PyObject *key)
00131 {
00132 TDB_DATA drec, krec;
00133 PyObject *result;
00134
00135 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize))
00136 return NULL;
00137
00138 drec = tdb_fetch(obj->tdb, krec);
00139
00140 if (!drec.dptr) {
00141 PyErr_SetString(PyExc_KeyError,
00142 PyString_AsString(key));
00143 return NULL;
00144 }
00145
00146 result = PyString_FromStringAndSize(drec.dptr, drec.dsize);
00147 free(drec.dptr);
00148
00149 return result;
00150 }
00151
00152 static int tdb_ass_subscript(tdb_hnd_object *obj, PyObject *key, PyObject *value)
00153 {
00154 TDB_DATA krec, drec;
00155
00156 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize)) {
00157 PyErr_SetString(PyExc_TypeError,
00158 "tdb mappings have string indices only");
00159 return -1;
00160 }
00161
00162 if (!obj->tdb) {
00163 PyErr_SetString(
00164 py_tdb_error, "tdb object has been closed");
00165 return -1;
00166 }
00167
00168 if (!value) {
00169
00170
00171
00172 if (tdb_delete(obj->tdb, krec) == -1) {
00173 PyErr_SetString(PyExc_KeyError,
00174 PyString_AsString(value));
00175 return -1;
00176 }
00177
00178 } else {
00179
00180
00181
00182 if (!PyArg_Parse(value, "s#", &drec.dptr, &drec.dsize)) {
00183 PyErr_SetString(PyExc_TypeError,
00184 "tdb mappings have string elements only");
00185 return -1;
00186 }
00187
00188 errno = 0;
00189
00190 if (tdb_store(obj->tdb, krec, drec, 0) < 0 ) {
00191 if (errno != 0)
00192 PyErr_SetFromErrno(py_tdb_error);
00193 else
00194 PyErr_SetString(
00195 py_tdb_error,
00196 (char *)tdb_errorstr(obj->tdb));
00197
00198 return -1;
00199 }
00200 }
00201
00202 return 0;
00203 }
00204
00205 static PyMappingMethods tdb_mapping = {
00206 (inquiry) tdb_hnd_length,
00207 (binaryfunc) tdb_hnd_subscript,
00208 (objobjargproc) tdb_ass_subscript
00209 };
00210
00211
00212
00213
00214
00215
00216
00217 PyObject *py_tdb_hnd_has_key(PyObject *self, PyObject *args)
00218 {
00219 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00220 TDB_DATA key;
00221
00222 if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
00223 return NULL;
00224
00225 if (!obj->tdb) {
00226 PyErr_SetString(
00227 py_tdb_error, "tdb object has been closed");
00228 return NULL;
00229 }
00230
00231 return PyInt_FromLong(tdb_exists(obj->tdb, key));
00232 }
00233
00234
00235
00236 static int tdb_traverse_keys(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
00237 void *state)
00238 {
00239 PyObject *key_list = (PyObject *)state;
00240
00241 PyList_Append(key_list,
00242 PyString_FromStringAndSize(key.dptr, key.dsize));
00243
00244 return 0;
00245 }
00246
00247 PyObject *py_tdb_hnd_keys(PyObject *self, PyObject *args)
00248 {
00249 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00250 PyObject *key_list = PyList_New(0);
00251
00252 if (!obj->tdb) {
00253 PyErr_SetString(py_tdb_error, "tdb object has been closed");
00254 return NULL;
00255 }
00256
00257 if (tdb_traverse(obj->tdb, tdb_traverse_keys, key_list) == -1) {
00258 PyErr_SetString(py_tdb_error, "error traversing tdb");
00259 Py_DECREF(key_list);
00260 return NULL;
00261 }
00262
00263 return key_list;
00264 }
00265
00266 PyObject *py_tdb_hnd_first_key(PyObject *self, PyObject *args)
00267 {
00268 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00269 TDB_DATA key;
00270
00271 if (!obj->tdb) {
00272 PyErr_SetString(py_tdb_error, "tdb object has been closed");
00273 return NULL;
00274 }
00275
00276 key = tdb_firstkey(obj->tdb);
00277
00278 return Py_BuildValue("s#", key.dptr, key.dsize);
00279 }
00280
00281 PyObject *py_tdb_hnd_next_key(PyObject *self, PyObject *py_oldkey)
00282 {
00283 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00284 TDB_DATA key, oldkey;
00285
00286 if (!obj->tdb) {
00287 PyErr_SetString(py_tdb_error, "tdb object has been closed");
00288 return NULL;
00289 }
00290
00291 if (!PyArg_Parse(py_oldkey, "s#", &oldkey.dptr, &oldkey.dsize))
00292 return NULL;
00293
00294 key = tdb_nextkey(obj->tdb, oldkey);
00295
00296 return Py_BuildValue("s#", key.dptr, key.dsize);
00297 }
00298
00299
00300
00301
00302
00303 PyObject *py_tdb_hnd_lock_all(PyObject *self, PyObject *args)
00304 {
00305 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00306 int result;
00307
00308 if (!obj->tdb) {
00309 PyErr_SetString(py_tdb_error, "tdb object has been closed");
00310 return NULL;
00311 }
00312
00313 result = tdb_lockall(obj->tdb);
00314
00315 return PyInt_FromLong(result != -1);
00316 }
00317
00318 PyObject *py_tdb_hnd_unlock_all(PyObject *self, PyObject *args)
00319 {
00320 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00321
00322 if (!obj->tdb) {
00323 PyErr_SetString(py_tdb_error, "tdb object has been closed");
00324 return NULL;
00325 }
00326
00327 tdb_unlockall(obj->tdb);
00328
00329 Py_INCREF(Py_None);
00330 return Py_None;
00331 }
00332
00333
00334
00335
00336 static BOOL make_lock_list(PyObject *py_keys, TDB_DATA **keys, int *num_keys)
00337 {
00338
00339
00340 if (!PyList_Check(py_keys) && !PyString_Check(py_keys)) {
00341 PyErr_SetString(PyExc_TypeError, "arg must be list of string");
00342 return False;
00343 }
00344
00345 if (PyList_Check(py_keys)) {
00346 int i;
00347
00348
00349
00350 *num_keys = PyList_Size(py_keys);
00351 *keys = (TDB_DATA *)SMB_XMALLOC_ARRAY(TDB_DATA, (*num_keys));
00352
00353 for (i = 0; i < *num_keys; i++) {
00354 PyObject *key = PyList_GetItem(py_keys, i);
00355
00356 if (!PyString_Check(key)) {
00357 PyErr_SetString(
00358 PyExc_TypeError,
00359 "list elements must be strings");
00360 return False;
00361 }
00362
00363 PyArg_Parse(key, "s#", &(*keys)[i].dptr,
00364 &(*keys)[i].dsize);
00365 }
00366
00367 } else {
00368
00369
00370
00371 *keys = (TDB_DATA *)SMB_XMALLOC_P(TDB_DATA);
00372 *num_keys = 1;
00373 PyArg_Parse(py_keys, "s#", &(*keys)->dptr, &(*keys)->dsize);
00374 }
00375
00376 return True;
00377 }
00378
00379
00380
00381
00382
00383 struct traverse_info {
00384 PyObject *callback;
00385 PyObject *state;
00386 };
00387
00388 static int tdb_traverse_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
00389 void *state)
00390 {
00391 struct traverse_info *info = state;
00392 PyObject *arglist, *py_result;
00393 int result;
00394
00395 arglist = Py_BuildValue("(s#s#O)", key.dptr, key.dsize, value.dptr,
00396 value.dsize, info->state);
00397
00398 py_result = PyEval_CallObject(info->callback, arglist);
00399
00400 Py_DECREF(arglist);
00401
00402 if (!PyInt_Check(py_result)) {
00403 result = 1;
00404 goto done;
00405 }
00406
00407 result = PyInt_AsLong(py_result);
00408
00409 done:
00410 Py_DECREF(py_result);
00411 return result;
00412 }
00413
00414 PyObject *py_tdb_hnd_traverse(PyObject *self, PyObject *args, PyObject *kw)
00415 {
00416 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00417 static char *kwlist[] = { "traverse_fn", "state", NULL };
00418 PyObject *state = Py_None, *callback;
00419 struct traverse_info info;
00420 int result;
00421
00422 if (!PyArg_ParseTupleAndKeywords(
00423 args, kw, "O|O", kwlist, &callback, &state))
00424 return NULL;
00425
00426 if (!PyCallable_Check(callback)) {
00427 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
00428 return NULL;
00429 }
00430
00431 Py_INCREF(callback);
00432 Py_INCREF(state);
00433
00434 info.callback = callback;
00435 info.state = state;
00436
00437 result = tdb_traverse(obj->tdb, tdb_traverse_traverse, &info);
00438
00439 Py_DECREF(callback);
00440 Py_DECREF(state);
00441
00442 return PyInt_FromLong(result);
00443 }
00444
00445 PyObject *py_tdb_hnd_chainlock(PyObject *self, PyObject *args)
00446 {
00447 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00448 TDB_DATA key;
00449 int result;
00450
00451 if (!obj->tdb) {
00452 PyErr_SetString(py_tdb_error, "tdb object has been closed");
00453 return NULL;
00454 }
00455
00456 if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
00457 return NULL;
00458
00459 result = tdb_chainlock(obj->tdb, key);
00460
00461 return PyInt_FromLong(result != -1);
00462 }
00463
00464 PyObject *py_tdb_hnd_chainunlock(PyObject *self, PyObject *args)
00465 {
00466 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00467 TDB_DATA key;
00468 int result;
00469
00470 if (!obj->tdb) {
00471 PyErr_SetString(py_tdb_error, "tdb object has been closed");
00472 return NULL;
00473 }
00474
00475 if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
00476 return NULL;
00477
00478 result = tdb_chainunlock(obj->tdb, key);
00479
00480 return PyInt_FromLong(result != -1);
00481 }
00482
00483 PyObject *py_tdb_hnd_lock_bystring(PyObject *self, PyObject *args)
00484 {
00485 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00486 int result, timeout = 30;
00487 char *s;
00488
00489 if (!obj->tdb) {
00490 PyErr_SetString(py_tdb_error, "tdb object has been closed");
00491 return NULL;
00492 }
00493
00494 if (!PyArg_ParseTuple(args, "s|i", &s, &timeout))
00495 return NULL;
00496
00497 result = tdb_lock_bystring_with_timeout(obj->tdb, s, timeout);
00498
00499 return PyInt_FromLong(result != -1);
00500 }
00501
00502 PyObject *py_tdb_hnd_unlock_bystring(PyObject *self, PyObject *args)
00503 {
00504 tdb_hnd_object *obj = (tdb_hnd_object *)self;
00505 char *s;
00506
00507 if (!obj->tdb) {
00508 PyErr_SetString(py_tdb_error, "tdb object has been closed");
00509 return NULL;
00510 }
00511
00512 if (!PyArg_ParseTuple(args, "s", &s))
00513 return NULL;
00514
00515 tdb_unlock_bystring(obj->tdb, s);
00516
00517 Py_INCREF(Py_None);
00518 return Py_None;
00519 }
00520
00521
00522
00523
00524
00525 static PyMethodDef tdb_methods[] = {
00526 { "open", (PyCFunction)py_tdb_open, METH_VARARGS | METH_KEYWORDS },
00527 { "close", (PyCFunction)py_tdb_close, METH_VARARGS },
00528 { NULL }
00529 };
00530
00531
00532
00533
00534
00535 static PyMethodDef tdb_hnd_methods[] = {
00536 { "keys", (PyCFunction)py_tdb_hnd_keys, METH_VARARGS },
00537 { "has_key", (PyCFunction)py_tdb_hnd_has_key, METH_VARARGS },
00538 { "first_key", (PyCFunction)py_tdb_hnd_first_key, METH_VARARGS },
00539 { "next_key", (PyCFunction)py_tdb_hnd_next_key, METH_VARARGS },
00540 { "lock_all", (PyCFunction)py_tdb_hnd_lock_all, METH_VARARGS },
00541 { "unlock_all", (PyCFunction)py_tdb_hnd_unlock_all, METH_VARARGS },
00542 { "traverse", (PyCFunction)py_tdb_hnd_traverse, METH_VARARGS | METH_KEYWORDS },
00543 { "chainlock", (PyCFunction)py_tdb_hnd_chainlock, METH_VARARGS | METH_KEYWORDS },
00544 { "chainunlock", (PyCFunction)py_tdb_hnd_chainunlock, METH_VARARGS | METH_KEYWORDS },
00545 { "lock_bystring", (PyCFunction)py_tdb_hnd_lock_bystring, METH_VARARGS | METH_KEYWORDS },
00546 { "unlock_bystring", (PyCFunction)py_tdb_hnd_unlock_bystring, METH_VARARGS | METH_KEYWORDS },
00547 { NULL }
00548 };
00549
00550
00551
00552 static void tdb_hnd_dealloc(PyObject* self)
00553 {
00554 tdb_hnd_object *hnd = (tdb_hnd_object *)self;
00555
00556 if (hnd->tdb) {
00557 tdb_close(hnd->tdb);
00558 hnd->tdb = NULL;
00559 }
00560 }
00561
00562
00563
00564 static PyObject *tdb_hnd_getattr(PyObject *self, char *attrname)
00565 {
00566 return Py_FindMethod(tdb_hnd_methods, self, attrname);
00567 }
00568
00569 static char tdb_hnd_type_doc[] =
00570 "Python wrapper for tdb.";
00571
00572 PyTypeObject tdb_hnd_type = {
00573 PyObject_HEAD_INIT(NULL)
00574 0,
00575 "tdb",
00576 sizeof(tdb_hnd_object),
00577 0,
00578 tdb_hnd_dealloc,
00579 0,
00580 tdb_hnd_getattr,
00581 0,
00582 0,
00583 0,
00584 0,
00585 0,
00586 &tdb_mapping,
00587 0,
00588 0,
00589 0,
00590 0,
00591 0,
00592 0,
00593 Py_TPFLAGS_DEFAULT,
00594 tdb_hnd_type_doc,
00595 };
00596
00597
00598
00599 static struct const_vals {
00600 char *name;
00601 uint32 value;
00602 } module_const_vals[] = {
00603
00604
00605
00606 { "TDB_DEFAULT", TDB_DEFAULT },
00607 { "TDB_CLEAR_IF_FIRST", TDB_CLEAR_IF_FIRST },
00608 { "TDB_INTERNAL", TDB_INTERNAL },
00609 { "TDB_NOLOCK", TDB_NOLOCK },
00610 { "TDB_NOMMAP", TDB_NOMMAP },
00611 { "TDB_CONVERT", TDB_CONVERT },
00612 { "TDB_BIGENDIAN", TDB_BIGENDIAN },
00613
00614 { NULL },
00615 };
00616
00617 static void const_init(PyObject *dict)
00618 {
00619 struct const_vals *tmp;
00620 PyObject *obj;
00621
00622 for (tmp = module_const_vals; tmp->name; tmp++) {
00623 obj = PyInt_FromLong(tmp->value);
00624 PyDict_SetItemString(dict, tmp->name, obj);
00625 Py_DECREF(obj);
00626 }
00627 }
00628
00629
00630
00631 void inittdb(void)
00632 {
00633 PyObject *module, *dict;
00634
00635
00636
00637 module = Py_InitModule("tdb", tdb_methods);
00638 dict = PyModule_GetDict(module);
00639
00640 py_tdb_error = PyErr_NewException("tdb.error", NULL, NULL);
00641 PyDict_SetItemString(dict, "error", py_tdb_error);
00642
00643
00644
00645 tdb_hnd_type.ob_type = &PyType_Type;
00646
00647 PyDict_SetItemString(dict, "tdb.hnd",
00648 (PyObject *)&tdb_hnd_type);
00649
00650
00651
00652 const_init(dict);
00653 }