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 backend
30 * Description: core functions for tdb backend
32 * Author: Andrew Tridgell
39 form a TDB_DATA for a record key
42 struct TDB_DATA
ltdb_key(const char *dn
)
47 asprintf(&key_str
, "DN=%s", dn
);
56 key
.dsize
= strlen(key_str
)+1;
62 lock the database for write - currently a single lock is used
64 static int ltdb_lock(struct ldb_context
*ldb
)
66 struct ltdb_private
*ltdb
= ldb
->private;
70 key
= ltdb_key("LDBLOCK");
75 ret
= tdb_chainlock(ltdb
->tdb
, key
);
83 unlock the database after a ltdb_lock()
85 static void ltdb_unlock(struct ldb_context
*ldb
)
87 struct ltdb_private
*ltdb
= ldb
->private;
90 key
= ltdb_key("LDBLOCK");
95 tdb_chainunlock(ltdb
->tdb
, key
);
101 store a record into the db
103 int ltdb_store(struct ldb_context
*ldb
, const struct ldb_message
*msg
, int flgs
)
105 struct ltdb_private
*ltdb
= ldb
->private;
106 TDB_DATA tdb_key
, tdb_data
;
109 tdb_key
= ltdb_key(msg
->dn
);
114 ret
= ltdb_pack_data(ldb
, msg
, &tdb_data
);
120 ret
= tdb_store(ltdb
->tdb
, tdb_key
, tdb_data
, flgs
);
125 ret
= ltdb_index_add(ldb
, msg
);
127 tdb_delete(ltdb
->tdb
, tdb_key
);
139 add a record to the database
141 static int ltdb_add(struct ldb_context
*ldb
, const struct ldb_message
*msg
)
145 if (ltdb_lock(ldb
) != 0) {
149 ret
= ltdb_store(ldb
, msg
, TDB_INSERT
);
158 delete a record from the database, not updating indexes (used for deleting
161 int ltdb_delete_noindex(struct ldb_context
*ldb
, const char *dn
)
163 struct ltdb_private
*ltdb
= ldb
->private;
167 tdb_key
= ltdb_key(dn
);
172 ret
= tdb_delete(ltdb
->tdb
, tdb_key
);
179 delete a record from the database
181 static int ltdb_delete(struct ldb_context
*ldb
, const char *dn
)
184 struct ldb_message msg
;
186 if (ltdb_lock(ldb
) != 0) {
190 /* in case any attribute of the message was indexed, we need
191 to fetch the old record */
192 ret
= ltdb_search_dn1(ldb
, dn
, &msg
);
194 /* not finding the old record is an error */
198 ret
= ltdb_delete_noindex(ldb
, dn
);
200 ltdb_search_dn1_free(ldb
, &msg
);
204 /* remove any indexed attributes */
205 ret
= ltdb_index_del(ldb
, &msg
);
207 ltdb_search_dn1_free(ldb
, &msg
);
219 find an element by attribute name. At the moment this does a linear search, it should
220 be re-coded to use a binary search once all places that modify records guarantee
223 return the index of the first matching element if found, otherwise -1
225 static int find_element(const struct ldb_message
*msg
, const char *name
)
228 for (i
=0;i
<msg
->num_elements
;i
++) {
229 if (strcmp(msg
->elements
[i
].name
, name
) == 0) {
238 add an element to an existing record. Assumes a elements array that we
239 can call re-alloc on, and assumed that we can re-use the data pointers from the
240 passed in additional values. Use with care!
242 returns 0 on success, -1 on failure (and sets errno)
244 static int msg_add_element(struct ldb_message
*msg
, struct ldb_message_element
*el
)
246 struct ldb_message_element
*e2
;
249 e2
= realloc_p(msg
->elements
, struct ldb_message_element
,
250 msg
->num_elements
+1);
258 e2
= &msg
->elements
[msg
->num_elements
];
261 e2
->flags
= el
->flags
;
263 if (el
->num_values
!= 0) {
264 e2
->values
= malloc_array_p(struct ldb_val
, el
->num_values
);
271 for (i
=0;i
<el
->num_values
;i
++) {
272 e2
->values
[i
] = el
->values
[i
];
274 e2
->num_values
= el
->num_values
;
282 delete all elements having a specified attribute name
284 static int msg_delete_attribute(struct ldb_message
*msg
, const char *name
)
287 struct ldb_message_element
*el2
;
289 el2
= malloc_array_p(struct ldb_message_element
, msg
->num_elements
);
295 for (i
=0;i
<msg
->num_elements
;i
++) {
296 if (strcmp(msg
->elements
[i
].name
, name
) != 0) {
297 el2
[count
++] = msg
->elements
[i
];
299 if (msg
->elements
[i
].values
) free(msg
->elements
[i
].values
);
303 msg
->num_elements
= count
;
304 if (msg
->elements
) free(msg
->elements
);
311 delete all elements matching an attribute name/value
313 return 0 on success, -1 on failure
315 static int msg_delete_element(struct ldb_message
*msg
,
317 const struct ldb_val
*val
)
320 struct ldb_message_element
*el
;
322 i
= find_element(msg
, name
);
327 el
= &msg
->elements
[i
];
329 for (i
=0;i
<el
->num_values
;i
++) {
330 if (ldb_val_equal(&el
->values
[i
], val
)) {
331 if (i
<el
->num_values
-1) {
332 memmove(&el
->values
[i
], &el
->values
[i
+1],
333 sizeof(el
->values
[i
])*el
->num_values
-(i
+1));
346 yuck - this is O(n^2). Luckily n is usually small so we probably
347 get away with it, but if we ever have really large attribute lists
348 then we'll need to look at this again
350 static int ltdb_modify(struct ldb_context
*ldb
, const struct ldb_message
*msg
)
352 struct ltdb_private
*ltdb
= ldb
->private;
353 TDB_DATA tdb_key
, tdb_data
;
354 struct ldb_message msg2
;
357 if (ltdb_lock(ldb
) != 0) {
361 tdb_key
= ltdb_key(msg
->dn
);
366 tdb_data
= tdb_fetch(ltdb
->tdb
, tdb_key
);
367 if (!tdb_data
.dptr
) {
372 ret
= ltdb_unpack_data(ldb
, &tdb_data
, &msg2
);
381 for (i
=0;i
<msg
->num_elements
;i
++) {
382 switch (msg
->elements
[i
].flags
& LDB_FLAG_MOD_MASK
) {
384 case LDB_FLAG_MOD_ADD
:
385 /* add this element to the message. fail if it
387 ret
= find_element(&msg2
, msg
->elements
[i
].name
);
392 if (msg_add_element(&msg2
, &msg
->elements
[i
]) != 0) {
397 case LDB_FLAG_MOD_REPLACE
:
398 /* replace all elements of this attribute name with the elements
400 if (msg_delete_attribute(&msg2
, msg
->elements
[i
].name
) != 0) {
403 /* add the replacement element */
404 if (msg_add_element(&msg2
, &msg
->elements
[i
]) != 0) {
409 case LDB_FLAG_MOD_DELETE
:
410 /* we could be being asked to delete all
411 values or just some values */
412 if (msg
->elements
[i
].num_values
== 0) {
413 if (msg_delete_attribute(&msg2
,
414 msg
->elements
[i
].name
) != 0) {
419 for (j
=0;j
<msg
->elements
[i
].num_values
;j
++) {
420 if (msg_delete_element(&msg2
,
421 msg
->elements
[i
].name
,
422 &msg
->elements
[i
].values
[j
]) != 0) {
430 /* we've made all the mods - save the modified record back into the database */
431 ret
= ltdb_store(ldb
, &msg2
, TDB_MODIFY
);
435 ltdb_unpack_data_free(&msg2
);
443 ltdb_unpack_data_free(&msg2
);
454 static int ltdb_close(struct ldb_context
*ldb
)
456 struct ltdb_private
*ltdb
= ldb
->private;
458 ret
= tdb_close(ltdb
->tdb
);
466 return extended error information
468 static const char *ltdb_errstring(struct ldb_context
*ldb
)
470 struct ltdb_private
*ltdb
= ldb
->private;
471 return tdb_errorstr(ltdb
->tdb
);
475 static const struct ldb_backend_ops ltdb_ops
= {
487 connect to the database
489 struct ldb_context
*ltdb_connect(const char *url
,
491 const char *options
[])
494 int tdb_flags
, open_flags
;
495 struct ltdb_private
*ltdb
;
497 struct ldb_context
*ldb
;
500 if (strncmp(url
, "tdb://", 6) != 0) {
507 tdb_flags
= TDB_DEFAULT
;
509 if (flags
& LDB_FLG_RDONLY
) {
510 open_flags
= O_RDONLY
;
512 open_flags
= O_CREAT
| O_RDWR
;
515 tdb
= tdb_open(path
, 0, tdb_flags
, open_flags
, 0666);
520 ltdb
= malloc_p(struct ltdb_private
);
530 ldb
= malloc_p(struct ldb_context
);
539 ldb
->ops
= <db_ops
;