r23798: updated old Temple Place FSF addresses to new URL
[Samba.git] / source / python / py_tdb.c
blobd72720f0ea3eb7dc0743a9e02a6a376c0871df36
1 /*
2 Python wrappers for TDB module
4 Copyright (C) Tim Potter, 2002-2003
6 ** NOTE! The following LGPL license applies to the tdb python
7 ** scripting library. This does NOT imply that all of Samba is
8 ** released under the LGPL
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
26 /* This symbol is used in both includes.h and Python.h which causes an
27 annoying compiler warning. */
29 #ifdef HAVE_FSTAT
30 #undef HAVE_FSTAT
31 #endif
33 #include "Python.h"
35 /* Tdb exception */
37 PyObject *py_tdb_error;
39 /* tdb handle object */
41 typedef struct {
42 PyObject_HEAD
43 TDB_CONTEXT *tdb;
44 } tdb_hnd_object;
46 PyTypeObject tdb_hnd_type;
48 PyObject *new_tdb_hnd_object(TDB_CONTEXT *tdb)
50 tdb_hnd_object *obj;
52 obj = PyObject_New(tdb_hnd_object, &tdb_hnd_type);
53 obj->tdb = tdb;
55 return (PyObject *)obj;
58 PyObject *py_tdb_close(PyObject *self, PyObject *args)
60 tdb_hnd_object *obj;
62 if (!PyArg_ParseTuple(args, "O!", &tdb_hnd_type, &obj))
63 return NULL;
65 if (tdb_close(obj->tdb) == -1) {
66 obj->tdb = NULL;
67 PyErr_SetString(py_tdb_error, strerror(errno));
68 return NULL;
71 obj->tdb = NULL;
73 Py_INCREF(Py_None);
74 return Py_None;
77 PyObject *py_tdb_open(PyObject *self, PyObject *args, PyObject *kw)
79 static char *kwlist[] = { "name", "hash_size", "tdb_flags",
80 "open_flags", "mode", NULL };
81 char *name;
82 int hash_size = 0, flags = TDB_DEFAULT, open_flags = -1, open_mode = 0600;
83 TDB_CONTEXT *tdb;
85 if (!PyArg_ParseTupleAndKeywords(
86 args, kw, "s|iiii", kwlist, &name, &hash_size, &flags,
87 &open_flags, &open_mode))
88 return NULL;
90 /* Default open_flags to read/write */
92 if (open_flags == -1) {
93 if (access(name, W_OK) == -1)
94 open_flags = O_RDONLY;
95 else
96 open_flags = O_RDWR;
99 if (!(tdb = tdb_open(name, hash_size, flags, open_flags, open_mode))) {
100 PyErr_SetString(py_tdb_error, strerror(errno));
101 return NULL;
104 return new_tdb_hnd_object(tdb);
108 * Allow a tdb to act as a python mapping (dictionary)
111 static int tdb_traverse_count(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
112 void *state)
114 /* Do nothing - tdb_traverse will return the number of records
115 traversed. */
117 return 0;
120 static int tdb_hnd_length(tdb_hnd_object *obj)
122 int result;
124 result = tdb_traverse(obj->tdb, tdb_traverse_count, NULL);
126 return result;
129 static PyObject *tdb_hnd_subscript(tdb_hnd_object *obj, PyObject *key)
131 TDB_DATA drec, krec;
132 PyObject *result;
134 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize))
135 return NULL;
137 drec = tdb_fetch(obj->tdb, krec);
139 if (!drec.dptr) {
140 PyErr_SetString(PyExc_KeyError,
141 PyString_AsString(key));
142 return NULL;
145 result = PyString_FromStringAndSize(drec.dptr, drec.dsize);
146 free(drec.dptr);
148 return result;
151 static int tdb_ass_subscript(tdb_hnd_object *obj, PyObject *key, PyObject *value)
153 TDB_DATA krec, drec;
155 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize)) {
156 PyErr_SetString(PyExc_TypeError,
157 "tdb mappings have string indices only");
158 return -1;
161 if (!obj->tdb) {
162 PyErr_SetString(
163 py_tdb_error, "tdb object has been closed");
164 return -1;
167 if (!value) {
169 /* Delete value */
171 if (tdb_delete(obj->tdb, krec) == -1) {
172 PyErr_SetString(PyExc_KeyError,
173 PyString_AsString(value));
174 return -1;
177 } else {
179 /* Set value */
181 if (!PyArg_Parse(value, "s#", &drec.dptr, &drec.dsize)) {
182 PyErr_SetString(PyExc_TypeError,
183 "tdb mappings have string elements only");
184 return -1;
187 errno = 0;
189 if (tdb_store(obj->tdb, krec, drec, 0) < 0 ) {
190 if (errno != 0)
191 PyErr_SetFromErrno(py_tdb_error);
192 else
193 PyErr_SetString(
194 py_tdb_error,
195 (char *)tdb_errorstr(obj->tdb));
197 return -1;
201 return 0;
204 static PyMappingMethods tdb_mapping = {
205 (inquiry) tdb_hnd_length,
206 (binaryfunc) tdb_hnd_subscript,
207 (objobjargproc) tdb_ass_subscript
211 * Utility methods
214 /* Return non-zero if a given key exists in the tdb */
216 PyObject *py_tdb_hnd_has_key(PyObject *self, PyObject *args)
218 tdb_hnd_object *obj = (tdb_hnd_object *)self;
219 TDB_DATA key;
221 if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
222 return NULL;
224 if (!obj->tdb) {
225 PyErr_SetString(
226 py_tdb_error, "tdb object has been closed");
227 return NULL;
230 return PyInt_FromLong(tdb_exists(obj->tdb, key));
233 /* Return a list of keys in the tdb */
235 static int tdb_traverse_keys(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
236 void *state)
238 PyObject *key_list = (PyObject *)state;
240 PyList_Append(key_list,
241 PyString_FromStringAndSize(key.dptr, key.dsize));
243 return 0;
246 PyObject *py_tdb_hnd_keys(PyObject *self, PyObject *args)
248 tdb_hnd_object *obj = (tdb_hnd_object *)self;
249 PyObject *key_list = PyList_New(0);
251 if (!obj->tdb) {
252 PyErr_SetString(py_tdb_error, "tdb object has been closed");
253 return NULL;
256 if (tdb_traverse(obj->tdb, tdb_traverse_keys, key_list) == -1) {
257 PyErr_SetString(py_tdb_error, "error traversing tdb");
258 Py_DECREF(key_list);
259 return NULL;
262 return key_list;
265 PyObject *py_tdb_hnd_first_key(PyObject *self, PyObject *args)
267 tdb_hnd_object *obj = (tdb_hnd_object *)self;
268 TDB_DATA key;
270 if (!obj->tdb) {
271 PyErr_SetString(py_tdb_error, "tdb object has been closed");
272 return NULL;
275 key = tdb_firstkey(obj->tdb);
277 return Py_BuildValue("s#", key.dptr, key.dsize);
280 PyObject *py_tdb_hnd_next_key(PyObject *self, PyObject *py_oldkey)
282 tdb_hnd_object *obj = (tdb_hnd_object *)self;
283 TDB_DATA key, oldkey;
285 if (!obj->tdb) {
286 PyErr_SetString(py_tdb_error, "tdb object has been closed");
287 return NULL;
290 if (!PyArg_Parse(py_oldkey, "s#", &oldkey.dptr, &oldkey.dsize))
291 return NULL;
293 key = tdb_nextkey(obj->tdb, oldkey);
295 return Py_BuildValue("s#", key.dptr, key.dsize);
299 * Locking routines
302 PyObject *py_tdb_hnd_lock_all(PyObject *self, PyObject *args)
304 tdb_hnd_object *obj = (tdb_hnd_object *)self;
305 int result;
307 if (!obj->tdb) {
308 PyErr_SetString(py_tdb_error, "tdb object has been closed");
309 return NULL;
312 result = tdb_lockall(obj->tdb);
314 return PyInt_FromLong(result != -1);
317 PyObject *py_tdb_hnd_unlock_all(PyObject *self, PyObject *args)
319 tdb_hnd_object *obj = (tdb_hnd_object *)self;
321 if (!obj->tdb) {
322 PyErr_SetString(py_tdb_error, "tdb object has been closed");
323 return NULL;
326 tdb_unlockall(obj->tdb);
328 Py_INCREF(Py_None);
329 return Py_None;
332 /* Return an array of keys from a python object which must be a string or a
333 list of strings. */
335 static BOOL make_lock_list(PyObject *py_keys, TDB_DATA **keys, int *num_keys)
337 /* Are we a list or a string? */
339 if (!PyList_Check(py_keys) && !PyString_Check(py_keys)) {
340 PyErr_SetString(PyExc_TypeError, "arg must be list of string");
341 return False;
344 if (PyList_Check(py_keys)) {
345 int i;
347 /* Turn python list into array of keys */
349 *num_keys = PyList_Size(py_keys);
350 *keys = (TDB_DATA *)SMB_XMALLOC_ARRAY(TDB_DATA, (*num_keys));
352 for (i = 0; i < *num_keys; i++) {
353 PyObject *key = PyList_GetItem(py_keys, i);
355 if (!PyString_Check(key)) {
356 PyErr_SetString(
357 PyExc_TypeError,
358 "list elements must be strings");
359 return False;
362 PyArg_Parse(key, "s#", &(*keys)[i].dptr,
363 &(*keys)[i].dsize);
366 } else {
368 /* Turn python string into a single key */
370 *keys = (TDB_DATA *)SMB_XMALLOC_P(TDB_DATA);
371 *num_keys = 1;
372 PyArg_Parse(py_keys, "s#", &(*keys)->dptr, &(*keys)->dsize);
375 return True;
379 * tdb traversal
382 struct traverse_info {
383 PyObject *callback;
384 PyObject *state;
387 static int tdb_traverse_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
388 void *state)
390 struct traverse_info *info = state;
391 PyObject *arglist, *py_result;
392 int result;
394 arglist = Py_BuildValue("(s#s#O)", key.dptr, key.dsize, value.dptr,
395 value.dsize, info->state);
397 py_result = PyEval_CallObject(info->callback, arglist);
399 Py_DECREF(arglist);
401 if (!PyInt_Check(py_result)) {
402 result = 1; /* Hmm - non-integer object returned by callback */
403 goto done;
406 result = PyInt_AsLong(py_result);
408 done:
409 Py_DECREF(py_result);
410 return result;
413 PyObject *py_tdb_hnd_traverse(PyObject *self, PyObject *args, PyObject *kw)
415 tdb_hnd_object *obj = (tdb_hnd_object *)self;
416 static char *kwlist[] = { "traverse_fn", "state", NULL };
417 PyObject *state = Py_None, *callback;
418 struct traverse_info info;
419 int result;
421 if (!PyArg_ParseTupleAndKeywords(
422 args, kw, "O|O", kwlist, &callback, &state))
423 return NULL;
425 if (!PyCallable_Check(callback)) {
426 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
427 return NULL;
430 Py_INCREF(callback);
431 Py_INCREF(state);
433 info.callback = callback;
434 info.state = state;
436 result = tdb_traverse(obj->tdb, tdb_traverse_traverse, &info);
438 Py_DECREF(callback);
439 Py_DECREF(state);
441 return PyInt_FromLong(result);
444 PyObject *py_tdb_hnd_chainlock(PyObject *self, PyObject *args)
446 tdb_hnd_object *obj = (tdb_hnd_object *)self;
447 TDB_DATA key;
448 int result;
450 if (!obj->tdb) {
451 PyErr_SetString(py_tdb_error, "tdb object has been closed");
452 return NULL;
455 if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
456 return NULL;
458 result = tdb_chainlock(obj->tdb, key);
460 return PyInt_FromLong(result != -1);
463 PyObject *py_tdb_hnd_chainunlock(PyObject *self, PyObject *args)
465 tdb_hnd_object *obj = (tdb_hnd_object *)self;
466 TDB_DATA key;
467 int result;
469 if (!obj->tdb) {
470 PyErr_SetString(py_tdb_error, "tdb object has been closed");
471 return NULL;
474 if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
475 return NULL;
477 result = tdb_chainunlock(obj->tdb, key);
479 return PyInt_FromLong(result != -1);
482 PyObject *py_tdb_hnd_lock_bystring(PyObject *self, PyObject *args)
484 tdb_hnd_object *obj = (tdb_hnd_object *)self;
485 int result, timeout = 30;
486 char *s;
488 if (!obj->tdb) {
489 PyErr_SetString(py_tdb_error, "tdb object has been closed");
490 return NULL;
493 if (!PyArg_ParseTuple(args, "s|i", &s, &timeout))
494 return NULL;
496 result = tdb_lock_bystring_with_timeout(obj->tdb, s, timeout);
498 return PyInt_FromLong(result != -1);
501 PyObject *py_tdb_hnd_unlock_bystring(PyObject *self, PyObject *args)
503 tdb_hnd_object *obj = (tdb_hnd_object *)self;
504 char *s;
506 if (!obj->tdb) {
507 PyErr_SetString(py_tdb_error, "tdb object has been closed");
508 return NULL;
511 if (!PyArg_ParseTuple(args, "s", &s))
512 return NULL;
514 tdb_unlock_bystring(obj->tdb, s);
516 Py_INCREF(Py_None);
517 return Py_None;
521 * Method dispatch table for this module
524 static PyMethodDef tdb_methods[] = {
525 { "open", (PyCFunction)py_tdb_open, METH_VARARGS | METH_KEYWORDS },
526 { "close", (PyCFunction)py_tdb_close, METH_VARARGS },
527 { NULL }
531 * Methods on a tdb object
534 static PyMethodDef tdb_hnd_methods[] = {
535 { "keys", (PyCFunction)py_tdb_hnd_keys, METH_VARARGS },
536 { "has_key", (PyCFunction)py_tdb_hnd_has_key, METH_VARARGS },
537 { "first_key", (PyCFunction)py_tdb_hnd_first_key, METH_VARARGS },
538 { "next_key", (PyCFunction)py_tdb_hnd_next_key, METH_VARARGS },
539 { "lock_all", (PyCFunction)py_tdb_hnd_lock_all, METH_VARARGS },
540 { "unlock_all", (PyCFunction)py_tdb_hnd_unlock_all, METH_VARARGS },
541 { "traverse", (PyCFunction)py_tdb_hnd_traverse, METH_VARARGS | METH_KEYWORDS },
542 { "chainlock", (PyCFunction)py_tdb_hnd_chainlock, METH_VARARGS | METH_KEYWORDS },
543 { "chainunlock", (PyCFunction)py_tdb_hnd_chainunlock, METH_VARARGS | METH_KEYWORDS },
544 { "lock_bystring", (PyCFunction)py_tdb_hnd_lock_bystring, METH_VARARGS | METH_KEYWORDS },
545 { "unlock_bystring", (PyCFunction)py_tdb_hnd_unlock_bystring, METH_VARARGS | METH_KEYWORDS },
546 { NULL }
549 /* Deallocate a tdb handle object */
551 static void tdb_hnd_dealloc(PyObject* self)
553 tdb_hnd_object *hnd = (tdb_hnd_object *)self;
555 if (hnd->tdb) {
556 tdb_close(hnd->tdb);
557 hnd->tdb = NULL;
561 /* Return tdb handle attributes */
563 static PyObject *tdb_hnd_getattr(PyObject *self, char *attrname)
565 return Py_FindMethod(tdb_hnd_methods, self, attrname);
568 static char tdb_hnd_type_doc[] =
569 "Python wrapper for tdb.";
571 PyTypeObject tdb_hnd_type = {
572 PyObject_HEAD_INIT(NULL)
574 "tdb",
575 sizeof(tdb_hnd_object),
577 tdb_hnd_dealloc, /* tp_dealloc*/
578 0, /* tp_print*/
579 tdb_hnd_getattr, /* tp_getattr*/
580 0, /* tp_setattr*/
581 0, /* tp_compare*/
582 0, /* tp_repr*/
583 0, /* tp_as_number*/
584 0, /* tp_as_sequence*/
585 &tdb_mapping, /* tp_as_mapping*/
586 0, /* tp_hash */
587 0, /* tp_call */
588 0, /* tp_str */
589 0, /* tp_getattro */
590 0, /* tp_setattro */
591 0, /* tp_as_buffer*/
592 Py_TPFLAGS_DEFAULT, /* tp_flags */
593 tdb_hnd_type_doc, /* tp_doc */
596 /* Constants */
598 static struct const_vals {
599 char *name;
600 uint32 value;
601 } module_const_vals[] = {
603 /* Flags for tdb_open() */
605 { "TDB_DEFAULT", TDB_DEFAULT },
606 { "TDB_CLEAR_IF_FIRST", TDB_CLEAR_IF_FIRST },
607 { "TDB_INTERNAL", TDB_INTERNAL },
608 { "TDB_NOLOCK", TDB_NOLOCK },
609 { "TDB_NOMMAP", TDB_NOMMAP },
610 { "TDB_CONVERT", TDB_CONVERT },
611 { "TDB_BIGENDIAN", TDB_BIGENDIAN },
613 { NULL },
616 static void const_init(PyObject *dict)
618 struct const_vals *tmp;
619 PyObject *obj;
621 for (tmp = module_const_vals; tmp->name; tmp++) {
622 obj = PyInt_FromLong(tmp->value);
623 PyDict_SetItemString(dict, tmp->name, obj);
624 Py_DECREF(obj);
628 /* Module initialisation */
630 void inittdb(void)
632 PyObject *module, *dict;
634 /* Initialise module */
636 module = Py_InitModule("tdb", tdb_methods);
637 dict = PyModule_GetDict(module);
639 py_tdb_error = PyErr_NewException("tdb.error", NULL, NULL);
640 PyDict_SetItemString(dict, "error", py_tdb_error);
642 /* Initialise policy handle object */
644 tdb_hnd_type.ob_type = &PyType_Type;
646 PyDict_SetItemString(dict, "tdb.hnd",
647 (PyObject *)&tdb_hnd_type);
649 /* Initialise constants */
651 const_init(dict);