4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
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.
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, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldb tdb cache functions
30 * Description: cache special records in a ldb/tdb
32 * Author: Andrew Tridgell
36 #include "ldb/include/includes.h"
38 #include "ldb/ldb_tdb/ldb_tdb.h"
40 #define LTDB_FLAG_CASE_INSENSITIVE (1<<0)
41 #define LTDB_FLAG_INTEGER (1<<1)
42 #define LTDB_FLAG_HIDDEN (1<<2)
43 #define LTDB_FLAG_OBJECTCLASS (1<<3)
45 /* valid attribute flags */
49 } ltdb_valid_attr_flags[] = {
50 { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE },
51 { "INTEGER", LTDB_FLAG_INTEGER },
52 { "HIDDEN", LTDB_FLAG_HIDDEN },
59 de-register any special handlers for @ATTRIBUTES
61 static void ltdb_attributes_unload(struct ldb_module *module)
63 struct ltdb_private *ltdb = module->private_data;
64 struct ldb_message *msg;
67 if (ltdb->cache->attributes == NULL) {
68 /* no previously loaded attributes */
72 msg = ltdb->cache->attributes;
73 for (i=0;i<msg->num_elements;i++) {
74 const struct ldb_attrib_handler *h;
75 /* this is rather ugly - a consequence of const handling */
76 h = ldb_attrib_handler(module->ldb, msg->elements[i].name);
77 ldb_remove_attrib_handler(module->ldb, msg->elements[i].name);
78 if (strcmp(h->attr, msg->elements[i].name) == 0) {
79 talloc_steal(msg, h->attr);
83 talloc_free(ltdb->cache->attributes);
84 ltdb->cache->attributes = NULL;
88 add up the attrib flags for a @ATTRIBUTES element
90 static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v)
94 for (i=0;i<el->num_values;i++) {
96 for (j=0;ltdb_valid_attr_flags[j].name;j++) {
97 if (strcmp(ltdb_valid_attr_flags[j].name,
98 (char *)el->values[i].data) == 0) {
99 value |= ltdb_valid_attr_flags[j].value;
103 if (ltdb_valid_attr_flags[j].name == NULL) {
112 register any special handlers from @ATTRIBUTES
114 static int ltdb_attributes_load(struct ldb_module *module)
116 struct ltdb_private *ltdb = module->private_data;
117 struct ldb_message *msg = ltdb->cache->attributes;
121 dn = ldb_dn_explode(module->ldb, LTDB_ATTRIBUTES);
122 if (dn == NULL) goto failed;
124 if (ltdb_search_dn1(module, dn, msg) == -1) {
129 /* mapping these flags onto ldap 'syntaxes' isn't strictly correct,
130 but its close enough for now */
131 for (i=0;i<msg->num_elements;i++) {
134 const struct ldb_attrib_handler *h;
135 struct ldb_attrib_handler h2;
137 if (ltdb_attributes_flags(&msg->elements[i], &flags) != 0) {
138 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'\n", msg->elements[i].name);
141 switch (flags & ~LTDB_FLAG_HIDDEN) {
143 syntax = LDB_SYNTAX_OCTET_STRING;
145 case LTDB_FLAG_CASE_INSENSITIVE:
146 syntax = LDB_SYNTAX_DIRECTORY_STRING;
148 case LTDB_FLAG_INTEGER:
149 syntax = LDB_SYNTAX_INTEGER;
152 ldb_debug(module->ldb, LDB_DEBUG_ERROR,
153 "Invalid flag combination 0x%x for '%s' in @ATTRIBUTES\n",
154 flags, msg->elements[i].name);
158 h = ldb_attrib_handler_syntax(module->ldb, syntax);
160 ldb_debug(module->ldb, LDB_DEBUG_ERROR,
161 "Invalid attribute syntax '%s' for '%s' in @ATTRIBUTES\n",
162 syntax, msg->elements[i].name);
166 h2.attr = talloc_strdup(module, msg->elements[i].name);
167 if (ldb_set_attrib_handlers(module->ldb, &h2, 1) != 0) {
179 register any subclasses from @SUBCLASSES
181 static int ltdb_subclasses_load(struct ldb_module *module)
183 struct ltdb_private *ltdb = module->private_data;
184 struct ldb_message *msg = ltdb->cache->subclasses;
188 dn = ldb_dn_explode(module->ldb, LTDB_SUBCLASSES);
189 if (dn == NULL) goto failed;
191 if (ltdb_search_dn1(module, dn, msg) == -1) {
197 for (i=0;i<msg->num_elements;i++) {
198 struct ldb_message_element *el = &msg->elements[i];
199 for (j=0;j<el->num_values;j++) {
200 if (ldb_subclass_add(module->ldb, el->name,
201 (char *)el->values[j].data) != 0) {
214 de-register any @SUBCLASSES
216 static void ltdb_subclasses_unload(struct ldb_module *module)
218 struct ltdb_private *ltdb = module->private_data;
219 struct ldb_message *msg;
222 if (ltdb->cache->subclasses == NULL) {
223 /* no previously loaded subclasses */
227 msg = ltdb->cache->subclasses;
228 for (i=0;i<msg->num_elements;i++) {
229 ldb_subclass_remove(module->ldb, msg->elements[i].name);
232 talloc_free(ltdb->cache->subclasses);
233 ltdb->cache->subclasses = NULL;
238 initialise the baseinfo record
240 static int ltdb_baseinfo_init(struct ldb_module *module)
242 struct ltdb_private *ltdb = module->private_data;
243 struct ldb_message *msg;
244 struct ldb_message_element el;
247 /* the initial sequence number must be different from the one
248 set in ltdb_cache_free(). Thanks to Jon for pointing this
250 const char *initial_sequence_number = "1";
252 ltdb->sequence_number = atof(initial_sequence_number);
254 msg = talloc(ltdb, struct ldb_message);
259 msg->num_elements = 1;
261 msg->dn = ldb_dn_explode(msg, LTDB_BASEINFO);
265 el.name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER);
272 val.data = (uint8_t *)talloc_strdup(msg, initial_sequence_number);
278 ret = ltdb_store(module, msg, TDB_INSERT);
291 free any cache records
293 static void ltdb_cache_free(struct ldb_module *module)
295 struct ltdb_private *ltdb = module->private_data;
297 ltdb->sequence_number = 0;
298 talloc_free(ltdb->cache);
305 int ltdb_cache_reload(struct ldb_module *module)
307 ltdb_attributes_unload(module);
308 ltdb_subclasses_unload(module);
309 ltdb_cache_free(module);
310 return ltdb_cache_load(module);
314 load the cache records
316 int ltdb_cache_load(struct ldb_module *module)
318 struct ltdb_private *ltdb = module->private_data;
319 struct ldb_dn *baseinfo_dn = NULL;
320 struct ldb_dn *indexlist_dn = NULL;
323 if (ltdb->cache == NULL) {
324 ltdb->cache = talloc_zero(ltdb, struct ltdb_cache);
325 if (ltdb->cache == NULL) goto failed;
326 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
327 ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message);
328 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
329 if (ltdb->cache->indexlist == NULL ||
330 ltdb->cache->subclasses == NULL ||
331 ltdb->cache->attributes == NULL) {
336 talloc_free(ltdb->cache->baseinfo);
337 ltdb->cache->baseinfo = talloc(ltdb->cache, struct ldb_message);
338 if (ltdb->cache->baseinfo == NULL) goto failed;
340 baseinfo_dn = ldb_dn_explode(module->ldb, LTDB_BASEINFO);
341 if (baseinfo_dn == NULL) goto failed;
343 if (ltdb_search_dn1(module, baseinfo_dn, ltdb->cache->baseinfo) == -1) {
347 /* possibly initialise the baseinfo */
348 if (!ltdb->cache->baseinfo->dn) {
349 if (ltdb_baseinfo_init(module) != 0) {
352 if (ltdb_search_dn1(module, baseinfo_dn, ltdb->cache->baseinfo) != 1) {
357 /* if the current internal sequence number is the same as the one
358 in the database then assume the rest of the cache is OK */
359 seq = ldb_msg_find_attr_as_double(ltdb->cache->baseinfo, LTDB_SEQUENCE_NUMBER, 0);
360 if (seq == ltdb->sequence_number) {
363 ltdb->sequence_number = seq;
365 talloc_free(ltdb->cache->last_attribute.name);
366 memset(<db->cache->last_attribute, 0, sizeof(ltdb->cache->last_attribute));
368 ltdb_attributes_unload(module);
369 ltdb_subclasses_unload(module);
371 talloc_free(ltdb->cache->indexlist);
372 talloc_free(ltdb->cache->subclasses);
374 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
375 ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message);
376 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
377 if (ltdb->cache->indexlist == NULL ||
378 ltdb->cache->subclasses == NULL ||
379 ltdb->cache->attributes == NULL) {
383 indexlist_dn = ldb_dn_explode(module->ldb, LTDB_INDEXLIST);
384 if (indexlist_dn == NULL) goto failed;
386 if (ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist) == -1) {
390 if (ltdb_attributes_load(module) == -1) {
393 if (ltdb_subclasses_load(module) == -1) {
398 talloc_free(baseinfo_dn);
399 talloc_free(indexlist_dn);
403 talloc_free(baseinfo_dn);
404 talloc_free(indexlist_dn);
410 increase the sequence number to indicate a database change
412 int ltdb_increase_sequence_number(struct ldb_module *module)
414 struct ltdb_private *ltdb = module->private_data;
415 struct ldb_message *msg;
416 struct ldb_message_element el;
421 msg = talloc(ltdb, struct ldb_message);
427 s = talloc_asprintf(msg, "%.0f", ltdb->sequence_number+1);
433 msg->num_elements = 1;
435 msg->dn = ldb_dn_explode(msg, LTDB_BASEINFO);
436 if (msg->dn == NULL) {
441 el.name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER);
442 if (el.name == NULL) {
449 el.flags = LDB_FLAG_MOD_REPLACE;
450 val.data = (uint8_t *)s;
451 val.length = strlen(s);
453 ret = ltdb_modify_internal(module, msg);
458 ltdb->sequence_number += 1;
466 return the attribute flags from the @ATTRIBUTES record
467 for the given attribute
469 int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name)
471 struct ltdb_private *ltdb = module->private_data;
472 const struct ldb_message_element *attr_el;
475 if (ltdb->cache->last_attribute.name &&
476 ldb_attr_cmp(ltdb->cache->last_attribute.name, attr_name) == 0) {
477 return ltdb->cache->last_attribute.flags;
480 /* objectclass is a special default case */
481 if (ldb_attr_cmp(attr_name, LTDB_OBJECTCLASS) == 0) {
482 ret = LTDB_FLAG_OBJECTCLASS | LTDB_FLAG_CASE_INSENSITIVE;
485 attr_el = ldb_msg_find_element(ltdb->cache->attributes, attr_name);
488 /* check if theres a wildcard attribute */
489 attr_el = ldb_msg_find_element(ltdb->cache->attributes, "*");
496 for (i = 0; i < attr_el->num_values; i++) {
497 for (j=0; ltdb_valid_attr_flags[j].name; j++) {
498 if (strcmp(ltdb_valid_attr_flags[j].name,
499 (char *)attr_el->values[i].data) == 0) {
500 ret |= ltdb_valid_attr_flags[j].value;
505 talloc_free(ltdb->cache->last_attribute.name);
507 ltdb->cache->last_attribute.name = talloc_strdup(ltdb->cache, attr_name);
508 ltdb->cache->last_attribute.flags = ret;
513 int ltdb_check_at_attributes_values(const struct ldb_val *value)
517 for (i = 0; ltdb_valid_attr_flags[i].name != NULL; i++) {
518 if ((strcmp(ltdb_valid_attr_flags[i].name, (char *)value->data) == 0)) {