summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/ldb.i
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2007-11-21 12:31:47 +0100
committerStefan Metzmacher <metze@samba.org>2007-12-21 05:45:56 +0100
commitefc0cc6be26b1866aca871b2deb37452c9ea47f6 (patch)
treecffe39b2b6d9ba83cdd767981577b9de15c99935 /source4/lib/ldb/ldb.i
parente5e2b64449a476552bbad49792b13f7501ecdc0c (diff)
downloadsamba-efc0cc6be26b1866aca871b2deb37452c9ea47f6.tar.gz
samba-efc0cc6be26b1866aca871b2deb37452c9ea47f6.tar.bz2
samba-efc0cc6be26b1866aca871b2deb37452c9ea47f6.zip
r26080: Import updated LDB bindings.
(This used to be commit 19342e66a7279805daf9f810b9dc808247110a8a)
Diffstat (limited to 'source4/lib/ldb/ldb.i')
-rw-r--r--source4/lib/ldb/ldb.i593
1 files changed, 460 insertions, 133 deletions
diff --git a/source4/lib/ldb/ldb.i b/source4/lib/ldb/ldb.i
index cdf1d66de1..9a55327a07 100644
--- a/source4/lib/ldb/ldb.i
+++ b/source4/lib/ldb/ldb.i
@@ -1,10 +1,11 @@
-/*
+/*
Unix SMB/CIFS implementation.
Swig interface to ldb.
Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
Copyright (C) 2006 Simo Sorce <idra@samba.org>
+ Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -24,82 +25,41 @@
License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-%module ldb
+%module(package="ldb") ldb
%{
-/* Some typedefs to help swig along */
-
-typedef unsigned char uint8_t;
-typedef unsigned long long uint64_t;
-typedef long long int64_t;
-
/* Include headers */
+#include <stdint.h>
#include <stdbool.h>
#include "talloc.h"
#include "ldb.h"
+#include "ldb_errors.h"
+
+typedef struct ldb_message ldb_msg;
+typedef struct ldb_context ldb;
+typedef struct ldb_dn ldb_dn;
+typedef struct ldb_ldif ldb_ldif;
+typedef struct ldb_message_element ldb_msg_element;
+typedef int ldb_error;
%}
-%include "carrays.i"
+%import "carrays.i"
+%import "typemaps.i"
%include "exception.i"
+%import "stdint.i"
-/*
- * Constants
- */
+%constant int SCOPE_DEFAULT = LDB_SCOPE_DEFAULT;
+%constant int SCOPE_BASE = LDB_SCOPE_BASE;
+%constant int SCOPE_ONELEVEL = LDB_SCOPE_ONELEVEL;
+%constant int SCOPE_SUBTREE = LDB_SCOPE_SUBTREE;
-#define LDB_SUCCESS 0
-#define LDB_ERR_OPERATIONS_ERROR 1
-#define LDB_ERR_PROTOCOL_ERROR 2
-#define LDB_ERR_TIME_LIMIT_EXCEEDED 3
-#define LDB_ERR_SIZE_LIMIT_EXCEEDED 4
-#define LDB_ERR_COMPARE_FALSE 5
-#define LDB_ERR_COMPARE_TRUE 6
-#define LDB_ERR_AUTH_METHOD_NOT_SUPPORTED 7
-#define LDB_ERR_STRONG_AUTH_REQUIRED 8
-/* 9 RESERVED */
-#define LDB_ERR_REFERRAL 10
-#define LDB_ERR_ADMIN_LIMIT_EXCEEDED 11
-#define LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION 12
-#define LDB_ERR_CONFIDENTIALITY_REQUIRED 13
-#define LDB_ERR_SASL_BIND_IN_PROGRESS 14
-#define LDB_ERR_NO_SUCH_ATTRIBUTE 16
-#define LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE 17
-#define LDB_ERR_INAPPROPRIATE_MATCHING 18
-#define LDB_ERR_CONSTRAINT_VIOLATION 19
-#define LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS 20
-#define LDB_ERR_INVALID_ATTRIBUTE_SYNTAX 21
-/* 22-31 unused */
-#define LDB_ERR_NO_SUCH_OBJECT 32
-#define LDB_ERR_ALIAS_PROBLEM 33
-#define LDB_ERR_INVALID_DN_SYNTAX 34
-/* 35 RESERVED */
-#define LDB_ERR_ALIAS_DEREFERENCING_PROBLEM 36
-/* 37-47 unused */
-#define LDB_ERR_INAPPROPRIATE_AUTHENTICATION 48
-#define LDB_ERR_INVALID_CREDENTIALS 49
-#define LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS 50
-#define LDB_ERR_BUSY 51
-#define LDB_ERR_UNAVAILABLE 52
-#define LDB_ERR_UNWILLING_TO_PERFORM 53
-#define LDB_ERR_LOOP_DETECT 54
-/* 55-63 unused */
-#define LDB_ERR_NAMING_VIOLATION 64
-#define LDB_ERR_OBJECT_CLASS_VIOLATION 65
-#define LDB_ERR_NOT_ALLOWED_ON_NON_LEAF 66
-#define LDB_ERR_NOT_ALLOWED_ON_RDN 67
-#define LDB_ERR_ENTRY_ALREADY_EXISTS 68
-#define LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED 69
-/* 70 RESERVED FOR CLDAP */
-#define LDB_ERR_AFFECTS_MULTIPLE_DSAS 71
-/* 72-79 unused */
-#define LDB_ERR_OTHER 80
-
-enum ldb_scope {LDB_SCOPE_DEFAULT=-1,
- LDB_SCOPE_BASE=0,
- LDB_SCOPE_ONELEVEL=1,
- LDB_SCOPE_SUBTREE=2};
+%constant int CHANGETYPE_NONE = LDB_CHANGETYPE_NONE;
+%constant int CHANGETYPE_ADD = LDB_CHANGETYPE_ADD;
+%constant int CHANGETYPE_DELETE = LDB_CHANGETYPE_DELETE;
+%constant int CHANGETYPE_MODIFY = LDB_CHANGETYPE_MODIFY;
/*
* Wrap struct ldb_context
@@ -114,16 +74,16 @@ enum ldb_scope {LDB_SCOPE_DEFAULT=-1,
"ldb context must be non-NULL");
}
+%typemap(check) ldb_msg * {
+ if ($1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "Message can not be None");
+}
+
/*
* Wrap a small bit of talloc
*/
-/* Use talloc_init() to create a parameter to pass to ldb_init(). Don't
- forget to free it using talloc_free() afterwards. */
-
-TALLOC_CTX *talloc_init(char *name);
-int talloc_free(TALLOC_CTX *ptr);
-
/*
* Wrap struct ldb_val
*/
@@ -139,103 +99,470 @@ int talloc_free(TALLOC_CTX *ptr);
}
%typemap(out) struct ldb_val {
- $result = PyString_FromStringAndSize($1.data, $1.length);
+ $result = PyString_FromStringAndSize((const char *)$1.data, $1.length);
}
-/*
- * Wrap struct ldb_result
- */
-
-%typemap(in, numinputs=0) struct ldb_result **OUT (struct ldb_result *temp_ldb_result) {
- $1 = &temp_ldb_result;
+%typemap(in) ldb_msg *add_msg (int dict_pos, int msg_pos, PyObject *key,
+ PyObject *value, ldb_msg_element *msgel) {
+ if (PyDict_Check($input)) {
+ $1 = ldb_msg_new(NULL);
+ $1->num_elements = PyDict_Size($input) - 1; /* dn isn't in there */
+ $1->elements = talloc_zero_array($1, struct ldb_message_element, $1->num_elements+1);
+ msg_pos = dict_pos = 0;
+ while (PyDict_Next($input, &dict_pos, &key, &value)) {
+ if (!strcmp(PyString_AsString(key), "dn")) {
+ if (ldb_dn_from_pyobject(value, &$1->dn) != 0)
+ SWIG_exception(SWIG_TypeError, "unable to convert dn");
+ } else {
+ msgel = ldb_msg_element_from_pyobject(value, 0, PyString_AsString(key));
+ memcpy(&$1->elements[msg_pos], msgel, sizeof(*msgel));
+ msg_pos++;
+ }
+ dict_pos++;
+ }
+
+ if ($1->dn == NULL)
+ SWIG_exception(SWIG_TypeError, "no dn set");
+ } else {
+ if (SWIG_ConvertPtr($input, &$1, SWIGTYPE_p_ldb_message, 0) != 0)
+ return NULL;
+ }
}
-%typemap(argout) struct ldb_result ** {
- resultobj = SWIG_NewPointerObj(*$1, SWIGTYPE_p_ldb_result, 0);
-}
-
-%types(struct ldb_result *);
-
-/*
- * Wrap struct ldb_message_element
- */
-
-%array_functions(struct ldb_val, ldb_val_array);
+%typemap(freearg) ldb_msg *add_msg {
+//talloc_free($1);
+}
-struct ldb_message_element {
- unsigned int flags;
- const char *name;
- unsigned int num_values;
- struct ldb_val *values;
-};
/*
- * Wrap struct ldb_message
+ * Wrap struct ldb_result
*/
-%array_functions(struct ldb_message_element, ldb_message_element_array);
+%typemap(in, numinputs=0) struct ldb_result **OUT (struct ldb_result *temp_ldb_result) {
+ $1 = &temp_ldb_result;
+}
-struct ldb_message {
- struct ldb_dn *dn;
- unsigned int num_elements;
- struct ldb_message_element *elements;
-};
+#ifdef SWIGPYTHON
+%typemap(argout) struct ldb_result ** (int i) {
+ $result = PyList_New((*$1)->count);
+ for (i = 0; i < (*$1)->count; i++) {
+ PyList_SetItem($result, i,
+ SWIG_NewPointerObj((*$1)->msgs[i], SWIGTYPE_p_ldb_message, 0)
+ );
+ }
+}
-/*
- * Wrap struct ldb_result
- */
+%typemap(in, numinputs=1) const char * const *attrs {
+ if ($input == Py_None) {
+ $1 = NULL;
+ } else if (PySequence_Check($input)) {
+ int i;
+ $1 = talloc_array(NULL, char *, PySequence_Size($input)+1);
+ for(i = 0; i < PySequence_Size($input); i++)
+ $1[i] = PyString_AsString(PySequence_GetItem($input, i));
+ $1[i] = NULL;
+ } else {
+ SWIG_exception(SWIG_TypeError, "expected sequence");
+ }
+}
-%array_functions(struct ldb_message *, ldb_message_ptr_array);
+%typemap(freearg) const char * const *attrs {
+ talloc_free($1);
+}
+#endif
-struct ldb_result {
- unsigned int count;
- struct ldb_message **msgs;
- char **refs;
- struct ldb_control **controls;
-};
+%types(struct ldb_result *);
/*
- * Wrap ldb functions
+ * Wrap struct ldb_dn
*/
-/* Initialisation */
+%rename(__str__) ldb_dn::get_linearized;
+%rename(__cmp__) ldb_dn::compare;
+%rename(__len__) ldb_dn::get_comp_num;
+%rename(Dn) ldb_dn;
+typedef struct ldb_dn {
+ %extend {
+ ldb_dn(ldb *ldb, const char *str)
+ {
+ ldb_dn *ret = ldb_dn_new(ldb, ldb, str);
+ /* ldb_dn_new() doesn't accept NULL as memory context, so
+ we do it this way... */
+ talloc_steal(NULL, ret);
+
+ if (ret == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "unable to parse dn string");
+fail:
+ return ret;
+ }
+ ~ldb_dn() { talloc_free($self); }
+ bool validate();
+ const char *get_casefold();
+ const char *get_linearized();
+ ldb_dn *parent() { return ldb_dn_get_parent(NULL, $self); }
+ int compare(ldb_dn *other);
+ bool is_valid();
+ bool is_special();
+ bool is_null();
+ bool check_special(const char *name);
+ int get_comp_num();
+ bool add_child(ldb_dn *child);
+ bool add_base(ldb_dn *base);
+ const char *canonical_str() {
+ return ldb_dn_canonical_string($self, $self);
+ }
+ const char *canonical_ex_str() {
+ return ldb_dn_canonical_ex_string($self, $self);
+ }
+#ifdef SWIGPYTHON
+ ldb_dn *__add__(ldb_dn *other)
+ {
+ ldb_dn *ret = ldb_dn_copy(NULL, $self);
+ ldb_dn_add_child(ret, other);
+ return ret;
+ }
+
+ /* FIXME: implement __getslice__ */
+#endif
+ }
+} ldb_dn;
+
+#ifdef SWIGPYTHON
+%inline {
+int ldb_dn_from_pyobject(PyObject *object, ldb_dn **dn)
+{
+ return SWIG_ConvertPtr(object, dn, SWIGTYPE_p_ldb_dn, 0);
+}
-int ldb_global_init(void);
-struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx);
+ldb_msg_element *ldb_msg_element_from_pyobject(PyObject *set_obj, int flags,
+ const char *attr_name)
+{
+ struct ldb_message_element *me = talloc(NULL, struct ldb_message_element);
+ me->name = attr_name;
+ me->flags = flags;
+ if (PyString_Check(set_obj)) {
+ me->num_values = 1;
+ me->values = talloc_array(me, struct ldb_val, me->num_values);
+ me->values[0].length = PyString_Size(set_obj);
+ me->values[0].data = (uint8_t *)talloc_strdup(me->values,
+ PyString_AsString(set_obj));
+ } else if (PySequence_Check(set_obj)) {
+ int i;
+ me->num_values = PySequence_Size(set_obj);
+ me->values = talloc_array(me, struct ldb_val, me->num_values);
+ for (i = 0; i < me->num_values; i++) {
+ PyObject *obj = PySequence_GetItem(set_obj, i);
+ me->values[i].length = PyString_Size(obj);
+ me->values[i].data = (uint8_t *)PyString_AsString(obj);
+ }
+ } else {
+ talloc_free(me);
+ me = NULL;
+ }
+
+ return me;
+}
-/* Error handling */
+PyObject *ldb_msg_element_to_set(ldb_msg_element *me)
+{
+ int i;
+ PyObject *result;
-const char *ldb_errstring(struct ldb_context *ldb);
-const char *ldb_strerror(int ldb_err);
+ /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
+ result = PyList_New(me->num_values);
-/* Top-level ldb operations */
+ for (i = 0; i < me->num_values; i++) {
+ PyList_SetItem(result, i,
+ PyString_FromStringAndSize((const char *)me->values[i].data,
+ me->values[i].length));
+ }
-int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[]);
+ return result;
+}
-int ldb_search(struct ldb_context *ldb, struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_result **OUT);
+}
+#endif
+
+/* ldb_message_element */
+%rename(__cmp__) ldb_message_element::compare;
+%rename(MessageElement) ldb_msg_element;
+typedef struct ldb_message_element {
+ %extend {
+#ifdef SWIGPYTHON
+ PyObject *__iter__(void)
+ {
+ return PyObject_GetIter(ldb_msg_element_to_set($self));
+ }
+
+ PyObject *__set__(void)
+ {
+ return ldb_msg_element_to_set($self);
+ }
+
+ ldb_msg_element(PyObject *set_obj, int flags=0, const char *name = NULL)
+ {
+ return ldb_msg_element_from_pyobject(set_obj, flags, name);
+ }
+#endif
+ ~ldb_msg_element() { talloc_free($self); }
+ int compare(ldb_msg_element *);
+ }
+} ldb_msg_element;
+
+/* ldb_message */
+
+%rename(Message) ldb_message;
+#ifdef SWIGPYTHON
+%rename(__delitem__) ldb_message::remove_attr;
+%typemap(out) ldb_msg_element * {
+ if ($1 == NULL)
+ PyErr_SetString(PyExc_KeyError, "no such element");
+ else
+ $result = SWIG_NewPointerObj($1, SWIGTYPE_p_ldb_message_element, 0);
+}
+%rename(__getitem__) ldb_message::find_element;
+//%typemap(out) ldb_msg_element *;
+
+
+%inline {
+ PyObject *ldb_msg_list_elements(ldb_msg *msg)
+ {
+ int i;
+ PyObject *obj = PyList_New(msg->num_elements);
+ for (i = 0; i < msg->num_elements; i++)
+ PyList_SetItem(obj, i, PyString_FromString(msg->elements[i].name));
+ return obj;
+ }
+}
-int ldb_delete(struct ldb_context *ldb, struct ldb_dn *dn);
+#endif
+
+typedef struct ldb_message {
+ ldb_dn *dn;
+
+ %extend {
+ ldb_msg(ldb_dn *dn = NULL) {
+ ldb_msg *ret = ldb_msg_new(NULL);
+ ret->dn = talloc_reference(ret, dn);
+ return ret;
+ }
+ ~ldb_msg() { talloc_free($self); }
+
+ ldb_msg_element *find_element(const char *name);
+
+#ifdef SWIGPYTHON
+ void __setitem__(const char *attr_name, ldb_msg_element *val)
+ {
+ struct ldb_message_element *el;
+
+ ldb_msg_remove_attr($self, attr_name);
+
+ el = talloc($self, struct ldb_message_element);
+ el->name = talloc_strdup(el, attr_name);
+ el->num_values = val->num_values;
+ el->values = talloc_reference(el, val->values);
+
+ ldb_msg_add($self, el, val->flags);
+ }
+
+ void __setitem__(const char *attr_name, PyObject *val)
+ {
+ struct ldb_message_element *el = ldb_msg_element_from_pyobject(
+ val, 0, attr_name);
+ talloc_steal($self, el);
+ ldb_msg_remove_attr($self, attr_name);
+ ldb_msg_add($self, el, el->flags);
+ }
+
+ unsigned int __len__() { return $self->num_elements; }
+
+ PyObject *keys(void)
+ {
+ return ldb_msg_list_elements($self);
+ }
+
+ PyObject *__iter__(void)
+ {
+ return PyObject_GetIter(ldb_msg_list_elements($self));
+ }
+#endif
+ void remove_attr(const char *name);
+ }
+} ldb_msg;
+
+/* FIXME: Convert ldb_result to 3-tuple:
+ (msgs, refs, controls)
+ */
-int ldb_rename(struct ldb_context *ldb, struct ldb_dn *olddn, struct ldb_dn *newdn);
+typedef struct ldb_ldif ldb_ldif;
-int ldb_add(struct ldb_context *ldb, const struct ldb_message *message);
+#ifdef SWIGPYTHON
+%{
+static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
+{
+ char *text;
+ PyObject *fn = context;
+
+ vasprintf(&text, fmt, ap);
+ PyObject_CallFunction(fn, "(i,s)", level, text);
+ free(text);
+}
+%}
-/* Ldb message operations */
+%typemap(in,numinputs=1) (void (*debug)(void *context, enum ldb_debug_level level, const char *fmt, va_list ap),
+ void *context) {
+ $1 = py_ldb_debug;
+ /* FIXME: Should be decreased somewhere as well. Perhaps register a destructor and
+ tie it to the ldb context ? */
+ Py_INCREF($input);
+ $2 = $input;
+}
+#endif
+
+%inline {
+ static PyObject *ldb_ldif_to_pyobject(ldb_ldif *ldif)
+ {
+ if (ldif == NULL) {
+ return Py_None;
+ } else {
+ return Py_BuildValue("(iO)", ldif->changetype,
+ SWIG_NewPointerObj(ldif->msg, SWIGTYPE_p_ldb_message, 0));
+ }
+ }
+}
-struct ldb_message *ldb_msg_new(void *mem_ctx);
+/*
+ * Wrap ldb errors
+ */
-struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, const char *attr_name);
+%{
+PyObject *PyExc_LdbError;
+%}
-int ldb_msg_add_value(struct ldb_message *msg, const char *attr_name, const struct ldb_val *val, struct ldb_message_element **return_el);
+%pythoncode %{
+ LdbError = _ldb.LdbError
+%}
-void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr);
+%init %{
+ PyExc_LdbError = PyErr_NewException("_ldb.LdbError", NULL, NULL);
+ PyDict_SetItemString(d, "LdbError", PyExc_LdbError);
+%}
-int ldb_msg_sanity_check(struct ldb_context *ldb, const struct ldb_message *msg);
+%ignore _LDB_ERRORS_H_;
+%ignore LDB_SUCCESS;
+%include "include/ldb_errors.h"
-/* DN operations */
+/*
+ * Wrap ldb functions
+ */
-/* struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); */
+%rename(Ldb) ldb;
+/* Top-level ldb operations */
+typedef struct ldb_context {
+ %typemap(out) ldb_error {
+ if ($1 != LDB_SUCCESS) {
+ PyErr_SetObject(PyExc_LdbError, Py_BuildValue("(i,s)", $1, ldb_strerror($1)));
+ SWIG_fail;
+ }
+ $result = Py_None;
+ };
+ %extend {
+ ldb(const char *url=NULL, unsigned int flags = 0,
+ const char *options[] = NULL)
+ {
+ ldb *ldb = ldb_init(NULL);
+
+ if (url != NULL) {
+ int ret;
+
+ ret = ldb_connect(ldb, url, flags, options);
+ if (ret != LDB_SUCCESS)
+ SWIG_exception(SWIG_ValueError, ldb_errstring(ldb));
+ }
+
+ return ldb;
+
+fail:
+ talloc_free(ldb);
+ return NULL;
+ }
+
+ ldb_error connect(const char *url, unsigned int flags = 0,
+ const char *options[] = NULL);
+
+ ~ldb() { talloc_free($self); }
+ ldb_error search(ldb_dn *base = NULL,
+ enum ldb_scope scope = LDB_SCOPE_DEFAULT,
+ const char *expression = NULL,
+ const char * const *attrs = NULL,
+ struct ldb_result **OUT);
+ ldb_error delete(ldb_dn *dn);
+ ldb_error rename(ldb_dn *olddn, ldb_dn *newdn);
+ ldb_error add(ldb_msg *add_msg);
+ ldb_error modify(ldb_msg *message);
+ ldb_dn *get_config_basedn();
+ ldb_dn *get_root_basedn();
+ ldb_dn *get_schema_basedn();
+ ldb_dn *get_default_basedn();
+ const char *errstring();
+ void set_create_perms(unsigned int perms);
+ void set_modules_dir(const char *path);
+ ldb_error set_debug(void (*debug)(void *context, enum ldb_debug_level level,
+ const char *fmt, va_list ap),
+ void *context);
+ ldb_error set_opaque(const char *name, void *value);
+ void *get_opaque(const char *name);
+ ldb_error transaction_start();
+ ldb_error transaction_commit();
+ ldb_error transaction_cancel();
+
+#ifdef SWIGPYTHON
+ bool __contains__(ldb_dn *dn)
+ {
+ struct ldb_result *result;
+
+ int ret = ldb_search($self, dn, LDB_SCOPE_BASE, NULL, NULL,
+ &result);
+
+ /* FIXME: Check ret and set exception if necessary */
+
+ return result->count > 0;
+ }
+
+ PyObject *parse_ldif(const char *s)
+ {
+ PyObject *list = PyList_New(0);
+ struct ldb_ldif *ldif;
+ while ((ldif = ldb_ldif_read_string($self, &s)) != NULL) {
+ PyList_Append(list, ldb_ldif_to_pyobject(ldif));
+ }
+ return PyObject_GetIter(list);
+ }
+
+#endif
+ }
+} ldb;
+
+%nodefault ldb_message;
+%nodefault Ldb;
+%nodefault Dn;
+
+%rename(valid_attr_name) ldb_valid_attr_name;
+int ldb_valid_attr_name(const char *s);
+
+typedef unsigned long time_t;
-/* char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *dn); */
+%{
+char *timestring(time_t t)
+{
+ char *tresult = ldb_timestring(NULL, t);
+ char *result = strdup(tresult);
+ talloc_free(tresult);
+ return result;
+}
+%}
+char *timestring(time_t t);
-%rename(ldb_context) Ldb;
+%rename(string_to_time) ldb_string_to_time;
+time_t ldb_string_to_time(const char *s);