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/ldb.h"
37 #include "ldb/include/ldb_private.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_WILDCARD (1<<2)
43 #define LTDB_FLAG_HIDDEN (1<<3)
44 #define LTDB_FLAG_OBJECTCLASS (1<<4)
46 /* valid attribute flags */
50 } ltdb_valid_attr_flags[] = {
51 { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE },
52 { "INTEGER", LTDB_FLAG_INTEGER },
53 { "WILDCARD", LTDB_FLAG_WILDCARD },
54 { "HIDDEN", LTDB_FLAG_HIDDEN },
61 de-register any special handlers for @ATTRIBUTES
63 static void ltdb_attributes_unload(struct ldb_module *module)
65 struct ltdb_private *ltdb = module->private_data;
66 struct ldb_message *msg;
69 if (ltdb->cache->attributes == NULL) {
70 /* no previously loaded attributes */
74 msg = ltdb->cache->attributes;
75 for (i=0;i<msg->num_elements;i++) {
76 const struct ldb_attrib_handler *h;
77 /* this is rather ugly - a consequence of const handling */
78 h = ldb_attrib_handler(module->ldb, msg->elements[i].name);
79 ldb_remove_attrib_handler(module->ldb, msg->elements[i].name);
80 if (strcmp(h->attr, msg->elements[i].name) == 0) {
81 talloc_steal(msg, h->attr);
85 talloc_free(ltdb->cache->attributes);
86 ltdb->cache->attributes = NULL;
90 add up the attrib flags for a @ATTRIBUTES element
92 static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v)
96 for (i=0;i<el->num_values;i++) {
98 for (j=0;ltdb_valid_attr_flags[j].name;j++) {
99 if (strcmp(ltdb_valid_attr_flags[j].name,
100 el->values[i].data) == 0) {
101 value |= ltdb_valid_attr_flags[j].value;
105 if (ltdb_valid_attr_flags[j].name == NULL) {
114 register any special handlers from @ATTRIBUTES
116 static int ltdb_attributes_load(struct ldb_module *module)
118 struct ltdb_private *ltdb = module->private_data;
119 struct ldb_message *msg = ltdb->cache->attributes;
122 if (ltdb_search_dn1(module, LTDB_ATTRIBUTES, msg) == -1) {
125 /* mapping these flags onto ldap 'syntaxes' isn't strictly correct,
126 but its close enough for now */
127 for (i=0;i<msg->num_elements;i++) {
130 const struct ldb_attrib_handler *h;
131 struct ldb_attrib_handler h2;
133 if (ltdb_attributes_flags(&msg->elements[i], &flags) != 0) {
134 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'\n", msg->elements[i].name);
137 switch (flags & ~LTDB_FLAG_HIDDEN) {
139 syntax = LDB_SYNTAX_OCTET_STRING;
141 case LTDB_FLAG_WILDCARD:
142 case LTDB_FLAG_WILDCARD | LTDB_FLAG_CASE_INSENSITIVE:
143 syntax = LDB_SYNTAX_WILDCARD;
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;
187 if (ltdb_search_dn1(module, LTDB_SUBCLASSES, msg) == -1) {
191 for (i=0;i<msg->num_elements;i++) {
192 struct ldb_message_element *el = &msg->elements[i];
193 for (j=0;j<el->num_values;j++) {
194 if (ldb_subclass_add(module->ldb, el->name, el->values[j].data) != 0) {
207 de-register any @SUBCLASSES
209 static void ltdb_subclasses_unload(struct ldb_module *module)
211 struct ltdb_private *ltdb = module->private_data;
212 struct ldb_message *msg;
215 if (ltdb->cache->subclasses == NULL) {
216 /* no previously loaded subclasses */
220 msg = ltdb->cache->subclasses;
221 for (i=0;i<msg->num_elements;i++) {
222 ldb_subclass_remove(module->ldb, msg->elements[i].name);
225 talloc_free(ltdb->cache->subclasses);
226 ltdb->cache->subclasses = NULL;
231 initialise the baseinfo record
233 static int ltdb_baseinfo_init(struct ldb_module *module)
235 struct ltdb_private *ltdb = module->private_data;
236 struct ldb_message *msg;
237 struct ldb_message_element el;
240 /* the initial sequence number must be different from the one
241 set in ltdb_cache_free(). Thanks to Jon for pointing this
243 const char *initial_sequence_number = "1";
245 ltdb->sequence_number = atof(initial_sequence_number);
247 msg = talloc(ltdb, struct ldb_message);
252 msg->num_elements = 1;
254 msg->dn = talloc_strdup(msg, LTDB_BASEINFO);
258 el.name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER);
265 val.data = talloc_strdup(msg, initial_sequence_number);
271 ret = ltdb_store(module, msg, TDB_INSERT);
284 free any cache records
286 static void ltdb_cache_free(struct ldb_module *module)
288 struct ltdb_private *ltdb = module->private_data;
290 ltdb->sequence_number = 0;
291 talloc_free(ltdb->cache);
298 int ltdb_cache_reload(struct ldb_module *module)
300 ltdb_attributes_unload(module);
301 ltdb_subclasses_unload(module);
302 ltdb_cache_free(module);
303 return ltdb_cache_load(module);
307 load the cache records
309 int ltdb_cache_load(struct ldb_module *module)
311 struct ltdb_private *ltdb = module->private_data;
314 if (ltdb->cache == NULL) {
315 ltdb->cache = talloc_zero(ltdb, struct ltdb_cache);
316 if (ltdb->cache == NULL) goto failed;
317 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
318 ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message);
319 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
320 if (ltdb->cache->indexlist == NULL ||
321 ltdb->cache->subclasses == NULL ||
322 ltdb->cache->attributes == NULL) {
327 talloc_free(ltdb->cache->baseinfo);
328 ltdb->cache->baseinfo = talloc(ltdb->cache, struct ldb_message);
329 if (ltdb->cache->baseinfo == NULL) goto failed;
331 if (ltdb_search_dn1(module, LTDB_BASEINFO, ltdb->cache->baseinfo) == -1) {
335 /* possibly initialise the baseinfo */
336 if (!ltdb->cache->baseinfo->dn) {
337 if (ltdb_baseinfo_init(module) != 0) {
340 if (ltdb_search_dn1(module, LTDB_BASEINFO, ltdb->cache->baseinfo) != 1) {
345 /* if the current internal sequence number is the same as the one
346 in the database then assume the rest of the cache is OK */
347 seq = ldb_msg_find_double(ltdb->cache->baseinfo, LTDB_SEQUENCE_NUMBER, 0);
348 if (seq == ltdb->sequence_number) {
351 ltdb->sequence_number = seq;
353 talloc_free(ltdb->cache->last_attribute.name);
354 memset(<db->cache->last_attribute, 0, sizeof(ltdb->cache->last_attribute));
356 ltdb_attributes_unload(module);
357 ltdb_subclasses_unload(module);
359 talloc_free(ltdb->cache->indexlist);
360 talloc_free(ltdb->cache->subclasses);
362 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
363 ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message);
364 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
365 if (ltdb->cache->indexlist == NULL ||
366 ltdb->cache->subclasses == NULL ||
367 ltdb->cache->attributes == NULL) {
371 if (ltdb_search_dn1(module, LTDB_INDEXLIST, ltdb->cache->indexlist) == -1) {
375 if (ltdb_attributes_load(module) == -1) {
378 if (ltdb_subclasses_load(module) == -1) {
391 increase the sequence number to indicate a database change
393 int ltdb_increase_sequence_number(struct ldb_module *module)
395 struct ltdb_private *ltdb = module->private_data;
396 struct ldb_message *msg;
397 struct ldb_message_element el;
402 msg = talloc(ltdb, struct ldb_message);
408 s = talloc_asprintf(msg, "%.0f", ltdb->sequence_number+1);
414 msg->num_elements = 1;
416 msg->dn = talloc_strdup(msg, LTDB_BASEINFO);
417 el.name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER);
420 el.flags = LDB_FLAG_MOD_REPLACE;
422 val.length = strlen(s);
424 ret = ltdb_modify_internal(module, msg);
429 ltdb->sequence_number += 1;
437 return the attribute flags from the @ATTRIBUTES record
438 for the given attribute
440 int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name)
442 struct ltdb_private *ltdb = module->private_data;
443 const struct ldb_message_element *attr_el;
446 if (ltdb->cache->last_attribute.name &&
447 ldb_attr_cmp(ltdb->cache->last_attribute.name, attr_name) == 0) {
448 return ltdb->cache->last_attribute.flags;
451 /* objectclass is a special default case */
452 if (ldb_attr_cmp(attr_name, LTDB_OBJECTCLASS) == 0) {
453 ret = LTDB_FLAG_OBJECTCLASS | LTDB_FLAG_CASE_INSENSITIVE;
456 attr_el = ldb_msg_find_element(ltdb->cache->attributes, attr_name);
459 /* check if theres a wildcard attribute */
460 attr_el = ldb_msg_find_element(ltdb->cache->attributes, "*");
467 for (i = 0; i < attr_el->num_values; i++) {
468 for (j=0; ltdb_valid_attr_flags[j].name; j++) {
469 if (strcmp(ltdb_valid_attr_flags[j].name,
470 attr_el->values[i].data) == 0) {
471 ret |= ltdb_valid_attr_flags[j].value;
476 talloc_free(ltdb->cache->last_attribute.name);
478 ltdb->cache->last_attribute.name = talloc_strdup(ltdb->cache, attr_name);
479 ltdb->cache->last_attribute.flags = ret;
484 int ltdb_check_at_attributes_values(const struct ldb_val *value)
488 for (i = 0; ltdb_valid_attr_flags[i].name != NULL; i++) {
489 if ((strcmp(ltdb_valid_attr_flags[i].name, value->data) == 0)) {