Support the 'PYTHON' environment variable.
[kai/samba.git] / lib / tdb / pytdb.c
index e20c79aa8f2649fd91a747290ed5cd4c0f5875cc..0faba562de93d028f9aacd9b51c7045b6f593caa 100644 (file)
@@ -9,7 +9,7 @@
      ** NOTE! The following LGPL license applies to the tdb
      ** library. This does NOT imply that all of Samba is released
      ** under the LGPL
-   
+
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <Python.h>
 #include "replace.h"
 #include "system/filesys.h"
 
-#include <Python.h>
 #ifndef Py_RETURN_NONE
 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
 #endif
@@ -41,7 +41,7 @@ typedef struct {
        bool closed;
 } PyTdbObject;
 
-PyAPI_DATA(PyTypeObject) PyTdb;
+staticforward PyTypeObject PyTdb;
 
 static void PyErr_SetTDBError(TDB_CONTEXT *tdb)
 {
@@ -77,15 +77,19 @@ static PyObject *PyString_FromTDB_DATA(TDB_DATA data)
 
 static PyObject *py_tdb_open(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-       char *name;
+       char *name = NULL;
        int hash_size = 0, tdb_flags = TDB_DEFAULT, flags = O_RDWR, mode = 0600;
        TDB_CONTEXT *ctx;
        PyTdbObject *ret;
        const char *kwnames[] = { "name", "hash_size", "tdb_flags", "flags", "mode", NULL };
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iiii", (char **)kwnames, &name, &hash_size, &tdb_flags, &flags, &mode))
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|siiii", (char **)kwnames, &name, &hash_size, &tdb_flags, &flags, &mode))
                return NULL;
 
+       if (name == NULL) {
+               tdb_flags |= TDB_INTERNAL;
+       }
+
        ctx = tdb_open(name, hash_size, tdb_flags, flags, mode);
        if (ctx == NULL) {
                PyErr_SetFromErrno(PyExc_IOError);
@@ -93,6 +97,11 @@ static PyObject *py_tdb_open(PyTypeObject *type, PyObject *args, PyObject *kwarg
        }
 
        ret = PyObject_New(PyTdbObject, &PyTdb);
+       if (!ret) {
+               tdb_close(ctx);
+               return NULL;
+       }
+
        ret->ctx = ctx;
        ret->closed = false;
        return (PyObject *)ret;
@@ -326,6 +335,8 @@ static PyObject *tdb_object_iter(PyTdbObject *self)
        PyTdbIteratorObject *ret;       
 
        ret = PyObject_New(PyTdbIteratorObject, &PyTdbIterator);
+       if (!ret)
+               return NULL;
        ret->current = tdb_firstkey(self->ctx);
        ret->iteratee = self;
        Py_INCREF(self);
@@ -339,6 +350,13 @@ static PyObject *obj_clear(PyTdbObject *self)
        Py_RETURN_NONE;
 }
 
+static PyObject *obj_repack(PyTdbObject *self)
+{
+       int ret = tdb_repack(self->ctx);
+       PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+       Py_RETURN_NONE;
+}
+
 static PyObject *obj_enable_seqnum(PyTdbObject *self)
 {
        tdb_enable_seqnum(self->ctx);
@@ -389,6 +407,8 @@ static PyMethodDef tdb_object_methods[] = {
        { "iterkeys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.iterkeys() -> iterator" },
        { "clear", (PyCFunction)obj_clear, METH_NOARGS, "S.clear() -> None\n"
                "Wipe the entire database." },
+       { "repack", (PyCFunction)obj_repack, METH_NOARGS, "S.repack() -> None\n"
+               "Repack the entire database." },
        { "enable_seqnum", (PyCFunction)obj_enable_seqnum, METH_NOARGS,
                "S.enable_seqnum() -> None" },
        { "increment_seqnum_nonblock", (PyCFunction)obj_increment_seqnum_nonblock, METH_NOARGS,
@@ -414,6 +434,11 @@ static PyObject *obj_get_map_size(PyTdbObject *self, void *closure)
        return PyInt_FromLong(tdb_map_size(self->ctx));
 }
 
+static PyObject *obj_get_freelist_size(PyTdbObject *self, void *closure)
+{
+       return PyInt_FromLong(tdb_freelist_size(self->ctx));
+}
+
 static PyObject *obj_get_flags(PyTdbObject *self, void *closure)
 {
        return PyInt_FromLong(tdb_get_flags(self->ctx));
@@ -433,6 +458,7 @@ static PyObject *obj_get_seqnum(PyTdbObject *self, void *closure)
 static PyGetSetDef tdb_object_getsetters[] = {
        { (char *)"hash_size", (getter)obj_get_hash_size, NULL, NULL },
        { (char *)"map_size", (getter)obj_get_map_size, NULL, NULL },
+       { (char *)"freelist_size", (getter)obj_get_freelist_size, NULL, NULL },
        { (char *)"flags", (getter)obj_get_flags, NULL, NULL },
        { (char *)"max_dead", NULL, (setter)obj_set_max_dead, NULL },
        { (char *)"filename", (getter)obj_get_filename, NULL, (char *)"The filename of this TDB file."},
@@ -442,16 +468,18 @@ static PyGetSetDef tdb_object_getsetters[] = {
 
 static PyObject *tdb_object_repr(PyTdbObject *self)
 {
-       return PyString_FromFormat("Tdb('%s')",
-               (tdb_get_flags(self->ctx) & TDB_INTERNAL) ? "<internal>"
-                                                         : tdb_name(self->ctx));
+       if (tdb_get_flags(self->ctx) & TDB_INTERNAL) {
+               return PyString_FromString("Tdb(<internal>)");
+       } else {
+               return PyString_FromFormat("Tdb('%s')", tdb_name(self->ctx));
+       }
 }
 
 static void tdb_object_dealloc(PyTdbObject *self)
 {
        if (!self->closed)
                tdb_close(self->ctx);
-       PyObject_Del(self);
+       self->ob_type->tp_free(self);
 }
 
 static PyObject *obj_getitem(PyTdbObject *self, PyObject *key)
@@ -510,7 +538,7 @@ static PyMappingMethods tdb_object_mapping = {
        .mp_subscript = (binaryfunc)obj_getitem,
        .mp_ass_subscript = (objobjargproc)obj_setitem,
 };
-PyTypeObject PyTdb = {
+static PyTypeObject PyTdb = {
        .tp_name = "Tdb",
        .tp_basicsize = sizeof(PyTdbObject),
        .tp_methods = tdb_object_methods,
@@ -560,9 +588,12 @@ void inittdb(void)
        PyModule_AddObject(m, "VOLATILE", PyInt_FromLong(TDB_VOLATILE));
        PyModule_AddObject(m, "ALLOW_NESTING", PyInt_FromLong(TDB_ALLOW_NESTING));
        PyModule_AddObject(m, "DISALLOW_NESTING", PyInt_FromLong(TDB_DISALLOW_NESTING));
+       PyModule_AddObject(m, "INCOMPATIBLE_HASH", PyInt_FromLong(TDB_INCOMPATIBLE_HASH));
 
        PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
 
+       PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION));
+
        Py_INCREF(&PyTdb);
        PyModule_AddObject(m, "Tdb", (PyObject *)&PyTdb);