⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldb_tdb.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    ldb database library   Copyright (C) Andrew Tridgell  2004   Copyright (C) Stefan Metzmacher  2004   Copyright (C) Simo Sorce       2006        ** NOTE! The following LGPL license applies to the ldb     ** 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   version 3 of the License, or (at your option) any later version.   This library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with this library; if not, see <http://www.gnu.org/licenses/>.*//* *  Name: ldb_tdb * *  Component: ldb tdb backend * *  Description: core functions for tdb backend * *  Author: Andrew Tridgell *  Author: Stefan Metzmacher * *  Modifications: * *  - description: make the module use asyncronous calls *    date: Feb 2006 *    Author: Simo Sorce */#include "ldb_includes.h"#include "ldb_tdb.h"/*  map a tdb error code to a ldb error code*/static int ltdb_err_map(enum TDB_ERROR tdb_code){	switch (tdb_code) {	case TDB_SUCCESS:		return LDB_SUCCESS;	case TDB_ERR_CORRUPT:	case TDB_ERR_OOM:	case TDB_ERR_EINVAL:		return LDB_ERR_OPERATIONS_ERROR;	case TDB_ERR_IO:		return LDB_ERR_PROTOCOL_ERROR;	case TDB_ERR_LOCK:	case TDB_ERR_NOLOCK:		return LDB_ERR_BUSY;	case TDB_ERR_LOCK_TIMEOUT:		return LDB_ERR_TIME_LIMIT_EXCEEDED;	case TDB_ERR_EXISTS:		return LDB_ERR_ENTRY_ALREADY_EXISTS;	case TDB_ERR_NOEXIST:		return LDB_ERR_NO_SUCH_OBJECT;	case TDB_ERR_RDONLY:		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;	}	return LDB_ERR_OTHER;}struct ldb_handle *init_ltdb_handle(struct ltdb_private *ltdb, struct ldb_module *module,				    struct ldb_request *req){	struct ltdb_context *ac;	struct ldb_handle *h;	h = talloc_zero(req, struct ldb_handle);	if (h == NULL) {		ldb_set_errstring(module->ldb, "Out of Memory");		return NULL;	}	h->module = module;	ac = talloc_zero(h, struct ltdb_context);	if (ac == NULL) {		ldb_set_errstring(module->ldb, "Out of Memory");		talloc_free(h);		return NULL;	}	h->private_data = (void *)ac;	h->state = LDB_ASYNC_INIT;	h->status = LDB_SUCCESS;	ac->module = module;	ac->context = req->context;	ac->callback = req->callback;	return h;}/*  form a TDB_DATA for a record key  caller frees  note that the key for a record can depend on whether the   dn refers to a case sensitive index record or not*/struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn){	struct ldb_context *ldb = module->ldb;	TDB_DATA key;	char *key_str = NULL;	const char *dn_folded = NULL;	/*	  most DNs are case insensitive. The exception is index DNs for	  case sensitive attributes	  there are 3 cases dealt with in this code:	  1) if the dn doesn't start with @ then uppercase the attribute             names and the attributes values of case insensitive attributes	  2) if the dn starts with @ then leave it alone - the indexing code handles	     the rest	*/	dn_folded = ldb_dn_get_casefold(dn);	if (!dn_folded) {		goto failed;	}	key_str = talloc_strdup(ldb, "DN=");	if (!key_str) {		goto failed;	}	key_str = talloc_strdup_append_buffer(key_str, dn_folded);	if (!key_str) {		goto failed;	}	key.dptr = (uint8_t *)key_str;	key.dsize = strlen(key_str) + 1;	return key;failed:	errno = ENOMEM;	key.dptr = NULL;	key.dsize = 0;	return key;}/*  check special dn's have valid attributes  currently only @ATTRIBUTES is checked*/int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg){	int i, j; 	if (! ldb_dn_is_special(msg->dn) ||	    ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {		return 0;	}	/* we have @ATTRIBUTES, let's check attributes are fine */	/* should we check that we deny multivalued attributes ? */	for (i = 0; i < msg->num_elements; i++) {		for (j = 0; j < msg->elements[i].num_values; j++) {			if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {				ldb_set_errstring(module->ldb, "Invalid attribute value in an @ATTRIBUTES entry");				return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;			}		}	}	return 0;}/*  we've made a modification to a dn - possibly reindex and   update sequence number*/static int ltdb_modified(struct ldb_module *module, struct ldb_dn *dn){	int ret = LDB_SUCCESS;	if (ldb_dn_is_special(dn) &&	    (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||	     ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {		ret = ltdb_reindex(module);	}	if (ret == LDB_SUCCESS &&	    !(ldb_dn_is_special(dn) &&	      ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {		ret = ltdb_increase_sequence_number(module);	}	return ret;}/*  store a record into the db*/int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs){	struct ltdb_private *ltdb =		talloc_get_type(module->private_data, struct ltdb_private);	TDB_DATA tdb_key, tdb_data;	int ret;	tdb_key = ltdb_key(module, msg->dn);	if (!tdb_key.dptr) {		return LDB_ERR_OTHER;	}	ret = ltdb_pack_data(module, msg, &tdb_data);	if (ret == -1) {		talloc_free(tdb_key.dptr);		return LDB_ERR_OTHER;	}	ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);	if (ret == -1) {		ret = ltdb_err_map(tdb_error(ltdb->tdb));		goto done;	}		ret = ltdb_index_add(module, msg);	if (ret != LDB_SUCCESS) {		tdb_delete(ltdb->tdb, tdb_key);	}done:	talloc_free(tdb_key.dptr);	talloc_free(tdb_data.dptr);	return ret;}static int ltdb_add_internal(struct ldb_module *module, const struct ldb_message *msg){	int ret;		ret = ltdb_check_special_dn(module, msg);	if (ret != LDB_SUCCESS) {		return ret;	}		if (ltdb_cache_load(module) != 0) {		return LDB_ERR_OPERATIONS_ERROR;	}	ret = ltdb_store(module, msg, TDB_INSERT);	if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {		ldb_asprintf_errstring(module->ldb, "Entry %s already exists", ldb_dn_get_linearized(msg->dn));		return ret;	}		if (ret == LDB_SUCCESS) {		ret = ltdb_index_one(module, msg, 1);		if (ret != LDB_SUCCESS) {			return ret;		}		ret = ltdb_modified(module, msg->dn);		if (ret != LDB_SUCCESS) {			return ret;		}	}	return ret;}/*  add a record to the database*/static int ltdb_add(struct ldb_module *module, struct ldb_request *req){	struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);	struct ltdb_context *ltdb_ac;	int tret, ret = LDB_SUCCESS;	if (check_critical_controls(req->controls)) {		return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;	}		req->handle = init_ltdb_handle(ltdb, module, req);	if (req->handle == NULL) {		return LDB_ERR_OPERATIONS_ERROR;	}	ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);	tret = ltdb_add_internal(module, req->op.add.message);	if (tret != LDB_SUCCESS) {		req->handle->status = tret;		goto done;	}		if (ltdb_ac->callback) {		ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);	}done:	req->handle->state = LDB_ASYNC_DONE;	return ret;}/*  delete a record from the database, not updating indexes (used for deleting  index records)*/int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn){	struct ltdb_private *ltdb =		talloc_get_type(module->private_data, struct ltdb_private);	TDB_DATA tdb_key;	int ret;	tdb_key = ltdb_key(module, dn);	if (!tdb_key.dptr) {		return LDB_ERR_OTHER;	}	ret = tdb_delete(ltdb->tdb, tdb_key);	talloc_free(tdb_key.dptr);	if (ret != 0) {		ret = ltdb_err_map(tdb_error(ltdb->tdb));	}	return ret;}static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn){	struct ldb_message *msg;	int ret;	msg = talloc(module, struct ldb_message);	if (msg == NULL) {		return LDB_ERR_OPERATIONS_ERROR;	}	/* in case any attribute of the message was indexed, we need	   to fetch the old record */	ret = ltdb_search_dn1(module, dn, msg);	if (ret != LDB_SUCCESS) {		/* not finding the old record is an error */		goto done;	}	ret = ltdb_delete_noindex(module, dn);	if (ret != LDB_SUCCESS) {		goto done;	}	/* remove one level attribute */	ret = ltdb_index_one(module, msg, 0);	if (ret != LDB_SUCCESS) {		goto done;	}	/* remove any indexed attributes */	ret = ltdb_index_del(module, msg);	if (ret != LDB_SUCCESS) {		goto done;	}	ret = ltdb_modified(module, dn);	if (ret != LDB_SUCCESS) {		goto done;	}done:	talloc_free(msg);	return ret;}/*  delete a record from the database*/static int ltdb_delete(struct ldb_module *module, struct ldb_request *req){	struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);	struct ltdb_context *ltdb_ac;	int tret, ret = LDB_SUCCESS;	if (check_critical_controls(req->controls)) {		return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;	}		req->handle = NULL;	if (ltdb_cache_load(module) != 0) {		return LDB_ERR_OPERATIONS_ERROR;	}	req->handle = init_ltdb_handle(ltdb, module, req);	if (req->handle == NULL) {		return LDB_ERR_OPERATIONS_ERROR;	}	ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);	tret = ltdb_delete_internal(module, req->op.del.dn);	if (tret != LDB_SUCCESS) {		req->handle->status = tret; 		goto done;	}	if (ltdb_ac->callback) {		ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);	}done:	req->handle->state = LDB_ASYNC_DONE;	return ret;}/*  find an element by attribute name. At the moment this does a linear search, it should  be re-coded to use a binary search once all places that modify records guarantee  sorted order  return the index of the first matching element if found, otherwise -1*/static int find_element(const struct ldb_message *msg, const char *name){	unsigned int i;	for (i=0;i<msg->num_elements;i++) {		if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {			return i;		}	}	return -1;}/*  add an element to an existing record. Assumes a elements array that we  can call re-alloc on, and assumed that we can re-use the data pointers from the   passed in additional values. Use with care!  returns 0 on success, -1 on failure (and sets errno)*/static int msg_add_element(struct ldb_context *ldb,			   struct ldb_message *msg, struct ldb_message_element *el){	struct ldb_message_element *e2;	unsigned int i;	e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element, 			      msg->num_elements+1);	if (!e2) {		errno = ENOMEM;		return -1;	}	msg->elements = e2;	e2 = &msg->elements[msg->num_elements];	e2->name = el->name;	e2->flags = el->flags;	e2->values = NULL;	if (el->num_values != 0) {		e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);		if (!e2->values) {			errno = ENOMEM;			return -1;		}	}	for (i=0;i<el->num_values;i++) {		e2->values[i] = el->values[i];	}	e2->num_values = el->num_values;	msg->num_elements++;	return 0;}/*  delete all elements having a specified attribute name*/static int msg_delete_attribute(struct ldb_module *module,				struct ldb_context *ldb,				struct ldb_message *msg, const char *name){	const char *dn;	unsigned int i, j;	dn = ldb_dn_get_linearized(msg->dn);	if (dn == NULL) {		return -1;	}	for (i=0;i<msg->num_elements;i++) {		if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {			for (j=0;j<msg->elements[i].num_values;j++) {				ltdb_index_del_value(module, dn, &msg->elements[i], j);			}			talloc_free(msg->elements[i].values);			if (msg->num_elements > (i+1)) {				memmove(&msg->elements[i], 					&msg->elements[i+1], 					sizeof(struct ldb_message_element)*					(msg->num_elements - (i+1)));			}			msg->num_elements--;			i--;			msg->elements = talloc_realloc(msg, msg->elements, 							 struct ldb_message_element, 							 msg->num_elements);		}	}	return 0;}/*  delete all elements matching an attribute name/value   return 0 on success, -1 on failure*/static int msg_delete_element(struct ldb_module *module,			      struct ldb_message *msg, 			      const char *name,			      const struct ldb_val *val){	struct ldb_context *ldb = module->ldb;	unsigned int i;	int found;	struct ldb_message_element *el;	const struct ldb_schema_attribute *a;	found = find_element(msg, name);	if (found == -1) {		return -1;	}	el = &msg->elements[found];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -