• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.0.25b/source/python/
1/*
2   Python wrappers for TDB module
3
4   Copyright (C) Tim Potter, 2002-2003
5
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
9
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 2 of the License, or (at your option) any later version.
14
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.
19
20   You should have received a copy of the GNU Lesser General Public
21   License along with this library; if not, write to the Free Software
22   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23*/
24
25#include "includes.h"
26
27/* This symbol is used in both includes.h and Python.h which causes an
28   annoying compiler warning. */
29
30#ifdef HAVE_FSTAT
31#undef HAVE_FSTAT
32#endif
33
34#include "Python.h"
35
36/* Tdb exception */
37
38PyObject *py_tdb_error;
39
40/* tdb handle object */
41
42typedef struct {
43	PyObject_HEAD
44	TDB_CONTEXT *tdb;
45} tdb_hnd_object;
46
47PyTypeObject tdb_hnd_type;
48
49PyObject *new_tdb_hnd_object(TDB_CONTEXT *tdb)
50{
51	tdb_hnd_object *obj;
52
53	obj = PyObject_New(tdb_hnd_object, &tdb_hnd_type);
54	obj->tdb = tdb;
55
56	return (PyObject *)obj;
57}
58
59PyObject *py_tdb_close(PyObject *self, PyObject *args)
60{
61	tdb_hnd_object *obj;
62
63	if (!PyArg_ParseTuple(args, "O!", &tdb_hnd_type, &obj))
64		return NULL;
65
66	if (tdb_close(obj->tdb) == -1) {
67		obj->tdb = NULL;
68		PyErr_SetString(py_tdb_error, strerror(errno));
69		return NULL;
70	}
71
72	obj->tdb = NULL;
73
74	Py_INCREF(Py_None);
75	return Py_None;
76}
77
78PyObject *py_tdb_open(PyObject *self, PyObject *args, PyObject *kw)
79{
80	static char *kwlist[] = { "name", "hash_size", "tdb_flags",
81				  "open_flags", "mode", NULL };
82	char *name;
83	int hash_size = 0, flags = TDB_DEFAULT, open_flags = -1, open_mode = 0600;
84	TDB_CONTEXT *tdb;
85
86	if (!PyArg_ParseTupleAndKeywords(
87		    args, kw, "s|iiii", kwlist, &name, &hash_size, &flags,
88		    &open_flags, &open_mode))
89		return NULL;
90
91	/* Default open_flags to read/write */
92
93	if (open_flags == -1) {
94		if (access(name, W_OK) == -1)
95			open_flags = O_RDONLY;
96		else
97			open_flags = O_RDWR;
98	}
99
100	if (!(tdb = tdb_open(name, hash_size, flags, open_flags, open_mode))) {
101		PyErr_SetString(py_tdb_error, strerror(errno));
102		return NULL;
103	}
104
105	return new_tdb_hnd_object(tdb);
106}
107
108/*
109 * Allow a tdb to act as a python mapping (dictionary)
110 */
111
112static int tdb_traverse_count(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
113			      void *state)
114{
115	/* Do nothing - tdb_traverse will return the number of records
116           traversed. */
117
118	return 0;
119}
120
121static int tdb_hnd_length(tdb_hnd_object *obj)
122{
123	int result;
124
125	result = tdb_traverse(obj->tdb, tdb_traverse_count, NULL);
126
127	return result;
128}
129
130static PyObject *tdb_hnd_subscript(tdb_hnd_object *obj, PyObject *key)
131{
132	TDB_DATA drec, krec;
133	PyObject *result;
134
135	if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize))
136		return NULL;
137
138	drec = tdb_fetch(obj->tdb, krec);
139
140	if (!drec.dptr) {
141		PyErr_SetString(PyExc_KeyError,
142				PyString_AsString(key));
143		return NULL;
144	}
145
146	result = PyString_FromStringAndSize(drec.dptr, drec.dsize);
147	free(drec.dptr);
148
149	return result;
150}
151
152static int tdb_ass_subscript(tdb_hnd_object *obj, PyObject *key, PyObject *value)
153{
154	TDB_DATA krec, drec;
155
156        if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize)) {
157		PyErr_SetString(PyExc_TypeError,
158				"tdb mappings have string indices only");
159		return -1;
160	}
161
162        if (!obj->tdb) {
163		PyErr_SetString(
164			py_tdb_error, "tdb object has been closed");
165		return -1;
166        }
167
168	if (!value) {
169
170		/* Delete value */
171
172		if (tdb_delete(obj->tdb, krec) == -1) {
173			PyErr_SetString(PyExc_KeyError,
174					PyString_AsString(value));
175			return -1;
176		}
177
178	} else {
179
180		/* Set value */
181
182		if (!PyArg_Parse(value, "s#", &drec.dptr, &drec.dsize)) {
183			PyErr_SetString(PyExc_TypeError,
184				    "tdb mappings have string elements only");
185			return -1;
186		}
187
188		errno = 0;
189
190		if (tdb_store(obj->tdb, krec, drec, 0) < 0 ) {
191			if (errno != 0)
192				PyErr_SetFromErrno(py_tdb_error);
193			else
194				PyErr_SetString(
195					py_tdb_error,
196					(char *)tdb_errorstr(obj->tdb));
197
198			return -1;
199		}
200	}
201
202	return 0;
203}
204
205static PyMappingMethods tdb_mapping = {
206	(inquiry) tdb_hnd_length,
207	(binaryfunc) tdb_hnd_subscript,
208	(objobjargproc) tdb_ass_subscript
209};
210
211/*
212 * Utility methods
213 */
214
215/* Return non-zero if a given key exists in the tdb */
216
217PyObject *py_tdb_hnd_has_key(PyObject *self, PyObject *args)
218{
219	tdb_hnd_object *obj = (tdb_hnd_object *)self;
220	TDB_DATA key;
221
222	if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
223		return NULL;
224
225        if (!obj->tdb) {
226		PyErr_SetString(
227			py_tdb_error, "tdb object has been closed");
228		return NULL;
229        }
230
231	return PyInt_FromLong(tdb_exists(obj->tdb, key));
232}
233
234/* Return a list of keys in the tdb */
235
236static int tdb_traverse_keys(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
237			     void *state)
238{
239	PyObject *key_list = (PyObject *)state;
240
241	PyList_Append(key_list,
242		      PyString_FromStringAndSize(key.dptr, key.dsize));
243
244	return 0;
245}
246
247PyObject *py_tdb_hnd_keys(PyObject *self, PyObject *args)
248{
249	tdb_hnd_object *obj = (tdb_hnd_object *)self;
250	PyObject *key_list = PyList_New(0);
251
252        if (!obj->tdb) {
253		PyErr_SetString(py_tdb_error, "tdb object has been closed");
254		return NULL;
255        }
256
257	if (tdb_traverse(obj->tdb, tdb_traverse_keys, key_list) == -1) {
258		PyErr_SetString(py_tdb_error, "error traversing tdb");
259		Py_DECREF(key_list);
260		return NULL;
261	}
262
263	return key_list;
264}
265
266PyObject *py_tdb_hnd_first_key(PyObject *self, PyObject *args)
267{
268	tdb_hnd_object *obj = (tdb_hnd_object *)self;
269	TDB_DATA key;
270
271        if (!obj->tdb) {
272		PyErr_SetString(py_tdb_error, "tdb object has been closed");
273		return NULL;
274        }
275
276	key = tdb_firstkey(obj->tdb);
277
278	return Py_BuildValue("s#", key.dptr, key.dsize);
279}
280
281PyObject *py_tdb_hnd_next_key(PyObject *self, PyObject *py_oldkey)
282{
283	tdb_hnd_object *obj = (tdb_hnd_object *)self;
284	TDB_DATA key, oldkey;
285
286        if (!obj->tdb) {
287		PyErr_SetString(py_tdb_error, "tdb object has been closed");
288		return NULL;
289        }
290
291	if (!PyArg_Parse(py_oldkey, "s#", &oldkey.dptr, &oldkey.dsize))
292		return NULL;
293
294	key = tdb_nextkey(obj->tdb, oldkey);
295
296	return Py_BuildValue("s#", key.dptr, key.dsize);
297}
298
299/*
300 * Locking routines
301 */
302
303PyObject *py_tdb_hnd_lock_all(PyObject *self, PyObject *args)
304{
305	tdb_hnd_object *obj = (tdb_hnd_object *)self;
306	int result;
307
308        if (!obj->tdb) {
309		PyErr_SetString(py_tdb_error, "tdb object has been closed");
310		return NULL;
311        }
312
313	result = tdb_lockall(obj->tdb);
314
315	return PyInt_FromLong(result != -1);
316}
317
318PyObject *py_tdb_hnd_unlock_all(PyObject *self, PyObject *args)
319{
320	tdb_hnd_object *obj = (tdb_hnd_object *)self;
321
322        if (!obj->tdb) {
323		PyErr_SetString(py_tdb_error, "tdb object has been closed");
324		return NULL;
325        }
326
327	tdb_unlockall(obj->tdb);
328
329	Py_INCREF(Py_None);
330	return Py_None;
331}
332
333/* Return an array of keys from a python object which must be a string or a
334   list of strings. */
335
336static BOOL make_lock_list(PyObject *py_keys, TDB_DATA **keys, int *num_keys)
337{
338	/* Are we a list or a string? */
339
340	if (!PyList_Check(py_keys) && !PyString_Check(py_keys)) {
341		PyErr_SetString(PyExc_TypeError, "arg must be list of string");
342		return False;
343	}
344
345	if (PyList_Check(py_keys)) {
346		int i;
347
348		/* Turn python list into array of keys */
349
350		*num_keys = PyList_Size(py_keys);
351		*keys = (TDB_DATA *)SMB_XMALLOC_ARRAY(TDB_DATA, (*num_keys));
352
353		for (i = 0; i < *num_keys; i++) {
354			PyObject *key = PyList_GetItem(py_keys, i);
355
356			if (!PyString_Check(key)) {
357				PyErr_SetString(
358					PyExc_TypeError,
359					"list elements must be strings");
360				return False;
361			}
362
363			PyArg_Parse(key, "s#", &(*keys)[i].dptr,
364				    &(*keys)[i].dsize);
365		}
366
367	} else {
368
369		/* Turn python string into a single key */
370
371		*keys = (TDB_DATA *)SMB_XMALLOC_P(TDB_DATA);
372		*num_keys = 1;
373		PyArg_Parse(py_keys, "s#", &(*keys)->dptr, &(*keys)->dsize);
374	}
375
376	return True;
377}
378
379/*
380 * tdb traversal
381 */
382
383struct traverse_info {
384	PyObject *callback;
385	PyObject *state;
386};
387
388static int tdb_traverse_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
389				 void *state)
390{
391	struct traverse_info *info = state;
392	PyObject *arglist, *py_result;
393	int result;
394
395	arglist = Py_BuildValue("(s#s#O)", key.dptr, key.dsize, value.dptr,
396				value.dsize, info->state);
397
398	py_result = PyEval_CallObject(info->callback, arglist);
399
400	Py_DECREF(arglist);
401
402	if (!PyInt_Check(py_result)) {
403		result = 1;	/* Hmm - non-integer object returned by callback */
404		goto done;
405	}
406
407	result = PyInt_AsLong(py_result);
408
409done:
410	Py_DECREF(py_result);
411	return result;
412}
413
414PyObject *py_tdb_hnd_traverse(PyObject *self, PyObject *args, PyObject *kw)
415{
416	tdb_hnd_object *obj = (tdb_hnd_object *)self;
417	static char *kwlist[] = { "traverse_fn", "state", NULL };
418	PyObject *state = Py_None, *callback;
419	struct traverse_info info;
420	int result;
421
422	if (!PyArg_ParseTupleAndKeywords(
423		    args, kw, "O|O", kwlist, &callback, &state))
424		return NULL;
425
426	if (!PyCallable_Check(callback)) {
427		PyErr_SetString(PyExc_TypeError, "parameter must be callable");
428		return NULL;
429        }
430
431	Py_INCREF(callback);
432	Py_INCREF(state);
433
434	info.callback = callback;
435	info.state = state;
436
437	result = tdb_traverse(obj->tdb, tdb_traverse_traverse, &info);
438
439	Py_DECREF(callback);
440	Py_DECREF(state);
441
442	return PyInt_FromLong(result);
443}
444
445PyObject *py_tdb_hnd_chainlock(PyObject *self, PyObject *args)
446{
447	tdb_hnd_object *obj = (tdb_hnd_object *)self;
448	TDB_DATA key;
449	int result;
450
451        if (!obj->tdb) {
452		PyErr_SetString(py_tdb_error, "tdb object has been closed");
453		return NULL;
454        }
455
456	if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
457		return NULL;
458
459	result = tdb_chainlock(obj->tdb, key);
460
461	return PyInt_FromLong(result != -1);
462}
463
464PyObject *py_tdb_hnd_chainunlock(PyObject *self, PyObject *args)
465{
466	tdb_hnd_object *obj = (tdb_hnd_object *)self;
467	TDB_DATA key;
468	int result;
469
470        if (!obj->tdb) {
471		PyErr_SetString(py_tdb_error, "tdb object has been closed");
472		return NULL;
473        }
474
475	if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
476		return NULL;
477
478	result = tdb_chainunlock(obj->tdb, key);
479
480	return PyInt_FromLong(result != -1);
481}
482
483PyObject *py_tdb_hnd_lock_bystring(PyObject *self, PyObject *args)
484{
485	tdb_hnd_object *obj = (tdb_hnd_object *)self;
486	int result, timeout = 30;
487	char *s;
488
489        if (!obj->tdb) {
490		PyErr_SetString(py_tdb_error, "tdb object has been closed");
491		return NULL;
492        }
493
494	if (!PyArg_ParseTuple(args, "s|i", &s, &timeout))
495		return NULL;
496
497	result = tdb_lock_bystring_with_timeout(obj->tdb, s, timeout);
498
499	return PyInt_FromLong(result != -1);
500}
501
502PyObject *py_tdb_hnd_unlock_bystring(PyObject *self, PyObject *args)
503{
504	tdb_hnd_object *obj = (tdb_hnd_object *)self;
505	char *s;
506
507        if (!obj->tdb) {
508		PyErr_SetString(py_tdb_error, "tdb object has been closed");
509		return NULL;
510        }
511
512	if (!PyArg_ParseTuple(args, "s", &s))
513		return NULL;
514
515	tdb_unlock_bystring(obj->tdb, s);
516
517	Py_INCREF(Py_None);
518	return Py_None;
519}
520
521/*
522 * Method dispatch table for this module
523 */
524
525static PyMethodDef tdb_methods[] = {
526	{ "open", (PyCFunction)py_tdb_open, METH_VARARGS | METH_KEYWORDS },
527	{ "close", (PyCFunction)py_tdb_close, METH_VARARGS },
528	{ NULL }
529};
530
531/*
532 * Methods on a tdb object
533 */
534
535static PyMethodDef tdb_hnd_methods[] = {
536	{ "keys", (PyCFunction)py_tdb_hnd_keys, METH_VARARGS },
537	{ "has_key", (PyCFunction)py_tdb_hnd_has_key, METH_VARARGS },
538	{ "first_key", (PyCFunction)py_tdb_hnd_first_key, METH_VARARGS },
539	{ "next_key", (PyCFunction)py_tdb_hnd_next_key, METH_VARARGS },
540	{ "lock_all", (PyCFunction)py_tdb_hnd_lock_all, METH_VARARGS },
541	{ "unlock_all", (PyCFunction)py_tdb_hnd_unlock_all, METH_VARARGS },
542	{ "traverse", (PyCFunction)py_tdb_hnd_traverse, METH_VARARGS | METH_KEYWORDS },
543	{ "chainlock", (PyCFunction)py_tdb_hnd_chainlock, METH_VARARGS | METH_KEYWORDS },
544	{ "chainunlock", (PyCFunction)py_tdb_hnd_chainunlock, METH_VARARGS | METH_KEYWORDS },
545	{ "lock_bystring", (PyCFunction)py_tdb_hnd_lock_bystring, METH_VARARGS | METH_KEYWORDS },
546	{ "unlock_bystring", (PyCFunction)py_tdb_hnd_unlock_bystring, METH_VARARGS | METH_KEYWORDS },
547	{ NULL }
548};
549
550/* Deallocate a tdb handle object */
551
552static void tdb_hnd_dealloc(PyObject* self)
553{
554        tdb_hnd_object *hnd = (tdb_hnd_object *)self;
555
556	if (hnd->tdb) {
557		tdb_close(hnd->tdb);
558		hnd->tdb = NULL;
559	}
560}
561
562/* Return tdb handle attributes */
563
564static PyObject *tdb_hnd_getattr(PyObject *self, char *attrname)
565{
566	return Py_FindMethod(tdb_hnd_methods, self, attrname);
567}
568
569static char tdb_hnd_type_doc[] =
570"Python wrapper for tdb.";
571
572PyTypeObject tdb_hnd_type = {
573	PyObject_HEAD_INIT(NULL)
574	0,
575	"tdb",
576	sizeof(tdb_hnd_object),
577	0,
578	tdb_hnd_dealloc,	/* tp_dealloc*/
579	0,			/* tp_print*/
580	tdb_hnd_getattr,	/* tp_getattr*/
581	0,			/* tp_setattr*/
582	0,			/* tp_compare*/
583	0,			/* tp_repr*/
584	0,			/* tp_as_number*/
585	0,			/* tp_as_sequence*/
586	&tdb_mapping,		/* tp_as_mapping*/
587	0,			/* tp_hash */
588	0,			/* tp_call */
589	0,			/* tp_str */
590	0,			/* tp_getattro */
591	0,			/* tp_setattro */
592	0,			/* tp_as_buffer*/
593	Py_TPFLAGS_DEFAULT,	/* tp_flags */
594	tdb_hnd_type_doc,	/* tp_doc */
595};
596
597/* Constants */
598
599static struct const_vals {
600	char *name;
601	uint32 value;
602} module_const_vals[] = {
603
604        /* Flags for tdb_open() */
605
606	{ "TDB_DEFAULT", TDB_DEFAULT },
607	{ "TDB_CLEAR_IF_FIRST", TDB_CLEAR_IF_FIRST },
608	{ "TDB_INTERNAL", TDB_INTERNAL },
609	{ "TDB_NOLOCK", TDB_NOLOCK },
610	{ "TDB_NOMMAP", TDB_NOMMAP },
611	{ "TDB_CONVERT", TDB_CONVERT },
612	{ "TDB_BIGENDIAN", TDB_BIGENDIAN },
613
614	{ NULL },
615};
616
617static void const_init(PyObject *dict)
618{
619	struct const_vals *tmp;
620	PyObject *obj;
621
622	for (tmp = module_const_vals; tmp->name; tmp++) {
623		obj = PyInt_FromLong(tmp->value);
624		PyDict_SetItemString(dict, tmp->name, obj);
625		Py_DECREF(obj);
626	}
627}
628
629/* Module initialisation */
630
631void inittdb(void)
632{
633	PyObject *module, *dict;
634
635	/* Initialise module */
636
637	module = Py_InitModule("tdb", tdb_methods);
638	dict = PyModule_GetDict(module);
639
640	py_tdb_error = PyErr_NewException("tdb.error", NULL, NULL);
641	PyDict_SetItemString(dict, "error", py_tdb_error);
642
643	/* Initialise policy handle object */
644
645	tdb_hnd_type.ob_type = &PyType_Type;
646
647	PyDict_SetItemString(dict, "tdb.hnd",
648			     (PyObject *)&tdb_hnd_type);
649
650	/* Initialise constants */
651
652	const_init(dict);
653}
654