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 3 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, see <http://www.gnu.org/licenses/>.
27 * Component: ldb message component utility functions
29 * Description: functions for manipulating ldb_message structures
31 * Author: Andrew Tridgell
34 #include "ldb_private.h"
37 create a new ldb_message in a given memory context (NULL for top level)
39 struct ldb_message
*ldb_msg_new(TALLOC_CTX
*mem_ctx
)
41 return talloc_zero(mem_ctx
, struct ldb_message
);
45 find an element in a message by attribute name
47 struct ldb_message_element
*ldb_msg_find_element(const struct ldb_message
*msg
,
48 const char *attr_name
)
51 for (i
=0;i
<msg
->num_elements
;i
++) {
52 if (ldb_attr_cmp(msg
->elements
[i
].name
, attr_name
) == 0) {
53 return &msg
->elements
[i
];
60 see if two ldb_val structures contain exactly the same data
61 return 1 for a match, 0 for a mis-match
63 int ldb_val_equal_exact(const struct ldb_val
*v1
, const struct ldb_val
*v2
)
65 if (v1
->length
!= v2
->length
) return 0;
66 if (v1
->data
== v2
->data
) return 1;
67 if (v1
->length
== 0) return 1;
69 if (memcmp(v1
->data
, v2
->data
, v1
->length
) == 0) {
77 find a value in an element
78 assumes case sensitive comparison
80 struct ldb_val
*ldb_msg_find_val(const struct ldb_message_element
*el
,
84 for (i
=0;i
<el
->num_values
;i
++) {
85 if (ldb_val_equal_exact(val
, &el
->values
[i
])) {
86 return &el
->values
[i
];
93 duplicate a ldb_val structure
95 struct ldb_val
ldb_val_dup(TALLOC_CTX
*mem_ctx
, const struct ldb_val
*v
)
98 v2
.length
= v
->length
;
99 if (v
->data
== NULL
) {
104 /* the +1 is to cope with buggy C library routines like strndup
105 that look one byte beyond */
106 v2
.data
= talloc_array(mem_ctx
, uint8_t, v
->length
+1);
112 memcpy(v2
.data
, v
->data
, v
->length
);
113 ((char *)v2
.data
)[v
->length
] = 0;
118 * Adds new empty element to msg->elements
120 static int _ldb_msg_add_el(struct ldb_message
*msg
,
121 struct ldb_message_element
**return_el
)
123 struct ldb_message_element
*els
;
126 * TODO: Find out a way to assert on input parameters.
127 * msg and return_el must be valid
130 els
= talloc_realloc(msg
, msg
->elements
,
131 struct ldb_message_element
, msg
->num_elements
+ 1);
133 return LDB_ERR_OPERATIONS_ERROR
;
136 ZERO_STRUCT(els
[msg
->num_elements
]);
141 *return_el
= &els
[msg
->num_elements
-1];
147 * Add an empty element with a given name to a message
149 int ldb_msg_add_empty(struct ldb_message
*msg
,
150 const char *attr_name
,
152 struct ldb_message_element
**return_el
)
155 struct ldb_message_element
*el
;
157 ret
= _ldb_msg_add_el(msg
, &el
);
158 if (ret
!= LDB_SUCCESS
) {
162 /* initialize newly added element */
164 el
->name
= talloc_strdup(msg
->elements
, attr_name
);
166 return LDB_ERR_OPERATIONS_ERROR
;
177 * Adds an element to a message.
179 * NOTE: Ownership of ldb_message_element fields
180 * is NOT transferred. Thus, if *el pointer
181 * is invalidated for some reason, this will
182 * corrupt *msg contents also
184 int ldb_msg_add(struct ldb_message
*msg
,
185 const struct ldb_message_element
*el
,
189 struct ldb_message_element
*el_new
;
190 /* We have to copy this, just in case *el is a pointer into
191 * what ldb_msg_add_empty() is about to realloc() */
192 struct ldb_message_element el_copy
= *el
;
194 ret
= _ldb_msg_add_el(msg
, &el_new
);
195 if (ret
!= LDB_SUCCESS
) {
199 el_new
->flags
= flags
;
200 el_new
->name
= el_copy
.name
;
201 el_new
->num_values
= el_copy
.num_values
;
202 el_new
->values
= el_copy
.values
;
208 add a value to a message
210 int ldb_msg_add_value(struct ldb_message
*msg
,
211 const char *attr_name
,
212 const struct ldb_val
*val
,
213 struct ldb_message_element
**return_el
)
215 struct ldb_message_element
*el
;
216 struct ldb_val
*vals
;
219 el
= ldb_msg_find_element(msg
, attr_name
);
221 ret
= ldb_msg_add_empty(msg
, attr_name
, 0, &el
);
222 if (ret
!= LDB_SUCCESS
) {
227 vals
= talloc_realloc(msg
->elements
, el
->values
, struct ldb_val
,
230 return LDB_ERR_OPERATIONS_ERROR
;
233 el
->values
[el
->num_values
] = *val
;
245 add a value to a message, stealing it into the 'right' place
247 int ldb_msg_add_steal_value(struct ldb_message
*msg
,
248 const char *attr_name
,
252 struct ldb_message_element
*el
;
254 ret
= ldb_msg_add_value(msg
, attr_name
, val
, &el
);
255 if (ret
== LDB_SUCCESS
) {
256 talloc_steal(el
->values
, val
->data
);
263 add a string element to a message
265 int ldb_msg_add_string(struct ldb_message
*msg
,
266 const char *attr_name
, const char *str
)
270 val
.data
= discard_const_p(uint8_t, str
);
271 val
.length
= strlen(str
);
273 if (val
.length
== 0) {
274 /* allow empty strings as non-existent attributes */
278 return ldb_msg_add_value(msg
, attr_name
, &val
, NULL
);
282 add a string element to a message, stealing it into the 'right' place
284 int ldb_msg_add_steal_string(struct ldb_message
*msg
,
285 const char *attr_name
, char *str
)
289 val
.data
= (uint8_t *)str
;
290 val
.length
= strlen(str
);
292 if (val
.length
== 0) {
293 /* allow empty strings as non-existent attributes */
297 return ldb_msg_add_steal_value(msg
, attr_name
, &val
);
301 add a DN element to a message
302 WARNING: this uses the linearized string from the dn, and does not
305 int ldb_msg_add_linearized_dn(struct ldb_message
*msg
, const char *attr_name
,
308 char *str
= ldb_dn_alloc_linearized(msg
, dn
);
311 /* we don't want to have unknown DNs added */
312 return LDB_ERR_OPERATIONS_ERROR
;
315 return ldb_msg_add_steal_string(msg
, attr_name
, str
);
319 add a printf formatted element to a message
321 int ldb_msg_add_fmt(struct ldb_message
*msg
,
322 const char *attr_name
, const char *fmt
, ...)
329 str
= talloc_vasprintf(msg
, fmt
, ap
);
332 if (str
== NULL
) return LDB_ERR_OPERATIONS_ERROR
;
334 val
.data
= (uint8_t *)str
;
335 val
.length
= strlen(str
);
337 return ldb_msg_add_steal_value(msg
, attr_name
, &val
);
341 compare two ldb_message_element structures
342 assumes case sensitive comparison
344 int ldb_msg_element_compare(struct ldb_message_element
*el1
,
345 struct ldb_message_element
*el2
)
349 if (el1
->num_values
!= el2
->num_values
) {
350 return el1
->num_values
- el2
->num_values
;
353 for (i
=0;i
<el1
->num_values
;i
++) {
354 if (!ldb_msg_find_val(el2
, &el1
->values
[i
])) {
363 compare two ldb_message_element structures
364 comparing by element name
366 int ldb_msg_element_compare_name(struct ldb_message_element
*el1
,
367 struct ldb_message_element
*el2
)
369 return ldb_attr_cmp(el1
->name
, el2
->name
);
373 convenience functions to return common types from a message
374 these return the first value if the attribute is multi-valued
376 const struct ldb_val
*ldb_msg_find_ldb_val(const struct ldb_message
*msg
,
377 const char *attr_name
)
379 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr_name
);
380 if (!el
|| el
->num_values
== 0) {
383 return &el
->values
[0];
386 int ldb_msg_find_attr_as_int(const struct ldb_message
*msg
,
387 const char *attr_name
,
390 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
391 char buf
[sizeof("-2147483648")];
395 if (!v
|| !v
->data
) {
396 return default_value
;
400 if (v
->length
>= sizeof(buf
)) {
401 return default_value
;
404 memcpy(buf
, v
->data
, v
->length
);
406 ret
= (int) strtoll(buf
, &end
, 10);
408 return default_value
;
410 if (end
&& end
[0] != '\0') {
411 return default_value
;
416 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message
*msg
,
417 const char *attr_name
,
418 unsigned int default_value
)
420 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
421 char buf
[sizeof("-2147483648")];
425 if (!v
|| !v
->data
) {
426 return default_value
;
430 if (v
->length
>= sizeof(buf
)) {
431 return default_value
;
434 memcpy(buf
, v
->data
, v
->length
);
436 ret
= (unsigned int) strtoll(buf
, &end
, 10);
439 ret
= (unsigned int) strtoull(buf
, &end
, 10);
441 return default_value
;
444 if (end
&& end
[0] != '\0') {
445 return default_value
;
450 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message
*msg
,
451 const char *attr_name
,
452 int64_t default_value
)
454 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
455 char buf
[sizeof("-9223372036854775808")];
459 if (!v
|| !v
->data
) {
460 return default_value
;
464 if (v
->length
>= sizeof(buf
)) {
465 return default_value
;
468 memcpy(buf
, v
->data
, v
->length
);
470 ret
= (int64_t) strtoll(buf
, &end
, 10);
472 return default_value
;
474 if (end
&& end
[0] != '\0') {
475 return default_value
;
480 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message
*msg
,
481 const char *attr_name
,
482 uint64_t default_value
)
484 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
485 char buf
[sizeof("-9223372036854775808")];
489 if (!v
|| !v
->data
) {
490 return default_value
;
494 if (v
->length
>= sizeof(buf
)) {
495 return default_value
;
498 memcpy(buf
, v
->data
, v
->length
);
500 ret
= (uint64_t) strtoll(buf
, &end
, 10);
503 ret
= (uint64_t) strtoull(buf
, &end
, 10);
505 return default_value
;
508 if (end
&& end
[0] != '\0') {
509 return default_value
;
514 double ldb_msg_find_attr_as_double(const struct ldb_message
*msg
,
515 const char *attr_name
,
516 double default_value
)
518 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
523 if (!v
|| !v
->data
) {
524 return default_value
;
526 buf
= talloc_strndup(msg
, (const char *)v
->data
, v
->length
);
528 return default_value
;
532 ret
= strtod(buf
, &end
);
535 return default_value
;
537 if (end
&& end
[0] != '\0') {
538 return default_value
;
543 int ldb_msg_find_attr_as_bool(const struct ldb_message
*msg
,
544 const char *attr_name
,
547 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
548 if (!v
|| !v
->data
) {
549 return default_value
;
551 if (v
->length
== 5 && strncasecmp((const char *)v
->data
, "FALSE", 5) == 0) {
554 if (v
->length
== 4 && strncasecmp((const char *)v
->data
, "TRUE", 4) == 0) {
557 return default_value
;
560 const char *ldb_msg_find_attr_as_string(const struct ldb_message
*msg
,
561 const char *attr_name
,
562 const char *default_value
)
564 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
565 if (!v
|| !v
->data
) {
566 return default_value
;
568 if (v
->data
[v
->length
] != '\0') {
569 return default_value
;
571 return (const char *)v
->data
;
574 struct ldb_dn
*ldb_msg_find_attr_as_dn(struct ldb_context
*ldb
,
576 const struct ldb_message
*msg
,
577 const char *attr_name
)
579 struct ldb_dn
*res_dn
;
580 const struct ldb_val
*v
;
582 v
= ldb_msg_find_ldb_val(msg
, attr_name
);
583 if (!v
|| !v
->data
) {
586 res_dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v
);
587 if ( ! ldb_dn_validate(res_dn
)) {
595 sort the elements of a message by name
597 void ldb_msg_sort_elements(struct ldb_message
*msg
)
599 TYPESAFE_QSORT(msg
->elements
, msg
->num_elements
,
600 ldb_msg_element_compare_name
);
604 shallow copy a message - copying only the elements array so that the caller
605 can safely add new elements without changing the message
607 struct ldb_message
*ldb_msg_copy_shallow(TALLOC_CTX
*mem_ctx
,
608 const struct ldb_message
*msg
)
610 struct ldb_message
*msg2
;
613 msg2
= talloc(mem_ctx
, struct ldb_message
);
614 if (msg2
== NULL
) return NULL
;
618 msg2
->elements
= talloc_array(msg2
, struct ldb_message_element
,
620 if (msg2
->elements
== NULL
) goto failed
;
622 for (i
=0;i
<msg2
->num_elements
;i
++) {
623 msg2
->elements
[i
] = msg
->elements
[i
];
635 copy a message, allocating new memory for all parts
637 struct ldb_message
*ldb_msg_copy(TALLOC_CTX
*mem_ctx
,
638 const struct ldb_message
*msg
)
640 struct ldb_message
*msg2
;
643 msg2
= ldb_msg_copy_shallow(mem_ctx
, msg
);
644 if (msg2
== NULL
) return NULL
;
646 msg2
->dn
= ldb_dn_copy(msg2
, msg2
->dn
);
647 if (msg2
->dn
== NULL
) goto failed
;
649 for (i
=0;i
<msg2
->num_elements
;i
++) {
650 struct ldb_message_element
*el
= &msg2
->elements
[i
];
651 struct ldb_val
*values
= el
->values
;
652 el
->name
= talloc_strdup(msg2
->elements
, el
->name
);
653 if (el
->name
== NULL
) goto failed
;
654 el
->values
= talloc_array(msg2
->elements
, struct ldb_val
, el
->num_values
);
655 for (j
=0;j
<el
->num_values
;j
++) {
656 el
->values
[j
] = ldb_val_dup(el
->values
, &values
[j
]);
657 if (el
->values
[j
].data
== NULL
&& values
[j
].length
!= 0) {
672 * Canonicalize a message, merging elements of the same name
674 struct ldb_message
*ldb_msg_canonicalize(struct ldb_context
*ldb
,
675 const struct ldb_message
*msg
)
678 struct ldb_message
*msg2
;
681 * Preserve previous behavior and allocate
682 * *msg2 into *ldb context
684 ret
= ldb_msg_normalize(ldb
, ldb
, msg
, &msg2
);
685 if (ret
!= LDB_SUCCESS
) {
693 * Canonicalize a message, merging elements of the same name
695 int ldb_msg_normalize(struct ldb_context
*ldb
,
697 const struct ldb_message
*msg
,
698 struct ldb_message
**_msg_out
)
701 struct ldb_message
*msg2
;
703 msg2
= ldb_msg_copy(mem_ctx
, msg
);
705 return LDB_ERR_OPERATIONS_ERROR
;
708 ldb_msg_sort_elements(msg2
);
710 for (i
=1; i
< msg2
->num_elements
; i
++) {
711 struct ldb_message_element
*el1
= &msg2
->elements
[i
-1];
712 struct ldb_message_element
*el2
= &msg2
->elements
[i
];
714 if (ldb_msg_element_compare_name(el1
, el2
) == 0) {
715 el1
->values
= talloc_realloc(msg2
->elements
,
716 el1
->values
, struct ldb_val
,
717 el1
->num_values
+ el2
->num_values
);
718 if (el1
->num_values
+ el2
->num_values
> 0 && el1
->values
== NULL
) {
720 return LDB_ERR_OPERATIONS_ERROR
;
722 memcpy(el1
->values
+ el1
->num_values
,
724 sizeof(struct ldb_val
) * el2
->num_values
);
725 el1
->num_values
+= el2
->num_values
;
726 talloc_free(discard_const_p(char, el2
->name
));
727 if ((i
+1) < msg2
->num_elements
) {
728 memmove(el2
, el2
+1, sizeof(struct ldb_message_element
) *
729 (msg2
->num_elements
- (i
+1)));
731 msg2
->num_elements
--;
742 * return a ldb_message representing the differences between msg1 and msg2.
743 * If you then use this in a ldb_modify() call,
744 * it can be used to save edits to a message
746 struct ldb_message
*ldb_msg_diff(struct ldb_context
*ldb
,
747 struct ldb_message
*msg1
,
748 struct ldb_message
*msg2
)
751 struct ldb_message
*mod
;
753 ldb_ret
= ldb_msg_difference(ldb
, ldb
, msg1
, msg2
, &mod
);
754 if (ldb_ret
!= LDB_SUCCESS
) {
762 * return a ldb_message representing the differences between msg1 and msg2.
763 * If you then use this in a ldb_modify() call it can be used to save edits to a message
765 * Result message is constructed as follows:
766 * - LDB_FLAG_MOD_ADD - elements found only in msg2
767 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
768 * Value for msg2 element is used
769 * - LDB_FLAG_MOD_DELETE - elements found only in msg2
771 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
773 int ldb_msg_difference(struct ldb_context
*ldb
,
775 struct ldb_message
*msg1
,
776 struct ldb_message
*msg2
,
777 struct ldb_message
**_msg_out
)
781 struct ldb_message
*mod
;
782 struct ldb_message_element
*el
;
783 TALLOC_CTX
*temp_ctx
;
785 temp_ctx
= talloc_new(mem_ctx
);
787 return LDB_ERR_OPERATIONS_ERROR
;
790 mod
= ldb_msg_new(temp_ctx
);
796 mod
->num_elements
= 0;
797 mod
->elements
= NULL
;
800 * Canonicalize *msg2 so we have no repeated elements
801 * Resulting message is allocated in *mod's mem context,
802 * as we are going to move some elements from *msg2 to
805 ldb_res
= ldb_msg_normalize(ldb
, mod
, msg2
, &msg2
);
806 if (ldb_res
!= LDB_SUCCESS
) {
810 /* look in msg2 to find elements that need to be added or modified */
811 for (i
=0;i
<msg2
->num_elements
;i
++) {
812 el
= ldb_msg_find_element(msg1
, msg2
->elements
[i
].name
);
814 if (el
&& ldb_msg_element_compare(el
, &msg2
->elements
[i
]) == 0) {
818 ldb_res
= ldb_msg_add(mod
,
820 el
? LDB_FLAG_MOD_REPLACE
: LDB_FLAG_MOD_ADD
);
821 if (ldb_res
!= LDB_SUCCESS
) {
826 /* look in msg1 to find elements that need to be deleted */
827 for (i
=0;i
<msg1
->num_elements
;i
++) {
828 el
= ldb_msg_find_element(msg2
, msg1
->elements
[i
].name
);
830 ldb_res
= ldb_msg_add_empty(mod
,
831 msg1
->elements
[i
].name
,
832 LDB_FLAG_MOD_DELETE
, NULL
);
833 if (ldb_res
!= LDB_SUCCESS
) {
839 /* steal resulting message into supplied context */
840 talloc_steal(mem_ctx
, mod
);
843 talloc_free(temp_ctx
);
847 talloc_free(temp_ctx
);
848 return LDB_ERR_OPERATIONS_ERROR
;
852 int ldb_msg_sanity_check(struct ldb_context
*ldb
,
853 const struct ldb_message
*msg
)
857 /* basic check on DN */
858 if (msg
->dn
== NULL
) {
859 ldb_set_errstring(ldb
, "ldb message lacks a DN!");
860 return LDB_ERR_INVALID_DN_SYNTAX
;
863 /* basic syntax checks */
864 for (i
= 0; i
< msg
->num_elements
; i
++) {
865 for (j
= 0; j
< msg
->elements
[i
].num_values
; j
++) {
866 if (msg
->elements
[i
].values
[j
].length
== 0) {
867 /* an attribute cannot be empty */
868 ldb_asprintf_errstring(ldb
, "Element %s has empty attribute in ldb message (%s)!",
869 msg
->elements
[i
].name
,
870 ldb_dn_get_linearized(msg
->dn
));
871 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
883 copy an attribute list. This only copies the array, not the elements
884 (ie. the elements are left as the same pointers)
886 const char **ldb_attr_list_copy(TALLOC_CTX
*mem_ctx
, const char * const *attrs
)
891 for (i
=0;attrs
&& attrs
[i
];i
++) /* noop */ ;
892 ret
= talloc_array(mem_ctx
, const char *, i
+1);
896 for (i
=0;attrs
&& attrs
[i
];i
++) {
905 copy an attribute list. This only copies the array, not the elements
906 (ie. the elements are left as the same pointers). The new attribute is added to the list.
908 const char **ldb_attr_list_copy_add(TALLOC_CTX
*mem_ctx
, const char * const *attrs
, const char *new_attr
)
914 for (i
=0;attrs
&& attrs
[i
];i
++) {
915 if (ldb_attr_cmp(attrs
[i
], new_attr
) == 0) {
920 return ldb_attr_list_copy(mem_ctx
, attrs
);
922 ret
= talloc_array(mem_ctx
, const char *, i
+2);
926 for (i
=0;attrs
&& attrs
[i
];i
++) {
936 return 1 if an attribute is in a list of attributes, or 0 otherwise
938 int ldb_attr_in_list(const char * const *attrs
, const char *attr
)
941 for (i
=0;attrs
&& attrs
[i
];i
++) {
942 if (ldb_attr_cmp(attrs
[i
], attr
) == 0) {
951 rename the specified attribute in a search result
953 int ldb_msg_rename_attr(struct ldb_message
*msg
, const char *attr
, const char *replace
)
955 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr
);
959 el
->name
= talloc_strdup(msg
->elements
, replace
);
960 if (el
->name
== NULL
) {
961 return LDB_ERR_OPERATIONS_ERROR
;
968 copy the specified attribute in a search result to a new attribute
970 int ldb_msg_copy_attr(struct ldb_message
*msg
, const char *attr
, const char *replace
)
972 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr
);
978 ret
= ldb_msg_add(msg
, el
, 0);
979 if (ret
!= LDB_SUCCESS
) {
982 return ldb_msg_rename_attr(msg
, attr
, replace
);
986 remove the specified element in a search result
988 void ldb_msg_remove_element(struct ldb_message
*msg
, struct ldb_message_element
*el
)
990 ptrdiff_t n
= (el
- msg
->elements
);
991 if (n
>= msg
->num_elements
) {
992 /* should we abort() here? */
995 if (n
!= msg
->num_elements
-1) {
996 memmove(el
, el
+1, ((msg
->num_elements
-1) - n
)*sizeof(*el
));
1003 remove the specified attribute in a search result
1005 void ldb_msg_remove_attr(struct ldb_message
*msg
, const char *attr
)
1007 struct ldb_message_element
*el
;
1009 while ((el
= ldb_msg_find_element(msg
, attr
)) != NULL
) {
1010 ldb_msg_remove_element(msg
, el
);
1015 return a LDAP formatted GeneralizedTime string
1017 char *ldb_timestring(TALLOC_CTX
*mem_ctx
, time_t t
)
1019 struct tm
*tm
= gmtime(&t
);
1027 /* we now excatly how long this string will be */
1028 ts
= talloc_array(mem_ctx
, char, 18);
1030 /* formatted like: 20040408072012.0Z */
1031 r
= snprintf(ts
, 18,
1032 "%04u%02u%02u%02u%02u%02u.0Z",
1033 tm
->tm_year
+1900, tm
->tm_mon
+1,
1034 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
,
1046 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1048 time_t ldb_string_to_time(const char *s
)
1052 if (s
== NULL
) return 0;
1054 memset(&tm
, 0, sizeof(tm
));
1055 if (sscanf(s
, "%04u%02u%02u%02u%02u%02u.0Z",
1056 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1057 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1067 convert a LDAP GeneralizedTime string in ldb_val format to a
1070 int ldb_val_to_time(const struct ldb_val
*v
, time_t *t
)
1074 if (v
== NULL
|| !v
->data
|| v
->length
< 17) {
1075 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1078 memset(&tm
, 0, sizeof(tm
));
1080 if (sscanf((char *)v
->data
, "%04u%02u%02u%02u%02u%02u.0Z",
1081 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1082 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1083 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1094 return a LDAP formatted UTCTime string
1096 char *ldb_timestring_utc(TALLOC_CTX
*mem_ctx
, time_t t
)
1098 struct tm
*tm
= gmtime(&t
);
1106 /* we now excatly how long this string will be */
1107 ts
= talloc_array(mem_ctx
, char, 14);
1109 /* formatted like: 20040408072012.0Z => 040408072012Z */
1110 r
= snprintf(ts
, 14,
1111 "%02u%02u%02u%02u%02u%02uZ",
1112 (tm
->tm_year
+1900)%100, tm
->tm_mon
+1,
1113 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
,
1125 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1127 time_t ldb_string_utc_to_time(const char *s
)
1131 if (s
== NULL
) return 0;
1133 memset(&tm
, 0, sizeof(tm
));
1134 if (sscanf(s
, "%02u%02u%02u%02u%02u%02uZ",
1135 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1136 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1139 if (tm
.tm_year
< 50) {
1149 dump a set of results to a file. Useful from within gdb
1151 void ldb_dump_results(struct ldb_context
*ldb
, struct ldb_result
*result
, FILE *f
)
1155 for (i
= 0; i
< result
->count
; i
++) {
1156 struct ldb_ldif ldif
;
1157 fprintf(f
, "# record %d\n", i
+1);
1158 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
1159 ldif
.msg
= result
->msgs
[i
];
1160 ldb_ldif_write_file(ldb
, f
, &ldif
);
1165 checks for a string attribute. Returns "1" on match and otherwise "0".
1167 int ldb_msg_check_string_attribute(const struct ldb_message
*msg
,
1168 const char *name
, const char *value
)
1170 struct ldb_message_element
*el
;
1173 el
= ldb_msg_find_element(msg
, name
);
1178 val
.data
= discard_const_p(uint8_t, value
);
1179 val
.length
= strlen(value
);
1181 if (ldb_msg_find_val(el
, &val
)) {
1190 compare a ldb_val to a string
1192 int ldb_val_string_cmp(const struct ldb_val
*v
, const char *str
)
1194 size_t len
= strlen(str
);
1195 if (len
!= v
->length
) {
1196 return len
- v
->length
;
1198 return strncmp((const char *)v
->data
, str
, len
);