summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@jelmer.uk>2017-01-15 15:18:48 +0000
committerJelmer Vernooij <jelmer@jelmer.uk>2017-01-15 15:18:48 +0000
commitbe03fa6817ca42e35691dc88a03f0b92b51741dd (patch)
treeb24c49bd94ad48171d1a93c1a82756f74887eb1e
parent3d57990b01dd1e9fc4c8902f868bb1d9e88e49b4 (diff)
New upstream version 1.1.29
-rw-r--r--ABI/ldb-1.1.27.sigs266
-rw-r--r--ABI/ldb-1.1.28.sigs266
-rw-r--r--ABI/ldb-1.1.29.sigs268
-rw-r--r--ABI/pyldb-util-1.1.27.sigs2
-rw-r--r--ABI/pyldb-util-1.1.28.sigs2
-rw-r--r--ABI/pyldb-util-1.1.29.sigs2
-rw-r--r--ABI/pyldb-util.py3-1.1.27.sigs2
-rw-r--r--ABI/pyldb-util.py3-1.1.28.sigs2
-rw-r--r--ABI/pyldb-util.py3-1.1.29.sigs2
-rw-r--r--buildtools/wafsamba/samba_autoconf.py2
-rw-r--r--buildtools/wafsamba/samba_perl.py3
-rwxr-xr-xbuildtools/wafsamba/wscript16
-rw-r--r--common/ldb.c74
-rw-r--r--common/ldb_attributes.c68
-rw-r--r--common/ldb_controls.c335
-rw-r--r--common/ldb_dn.c29
-rw-r--r--common/ldb_match.c4
-rw-r--r--common/ldb_modules.c7
-rw-r--r--common/ldb_pack.c113
-rw-r--r--include/ldb.h16
-rw-r--r--include/ldb_module.h36
-rw-r--r--include/ldb_private.h12
-rw-r--r--ldb_map/ldb_map.c7
-rw-r--r--ldb_map/ldb_map_outbound.c2
-rw-r--r--ldb_tdb/ldb_cache.c144
-rw-r--r--ldb_tdb/ldb_index.c136
-rw-r--r--ldb_tdb/ldb_search.c219
-rw-r--r--ldb_tdb/ldb_tdb.c33
-rw-r--r--ldb_tdb/ldb_tdb.h8
-rw-r--r--lib/replace/closefrom.c138
-rw-r--r--lib/replace/replace.h10
-rw-r--r--lib/replace/snprintf.c6
-rw-r--r--lib/replace/system/wait.h2
-rw-r--r--lib/replace/test/testsuite.c33
-rw-r--r--lib/replace/wscript25
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.6.sigs13
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.7.sigs13
-rw-r--r--lib/talloc/ABI/pytalloc-util-2.1.8.sigs13
-rw-r--r--lib/talloc/ABI/pytalloc-util.py3-2.1.6.sigs12
-rw-r--r--lib/talloc/ABI/pytalloc-util.py3-2.1.7.sigs12
-rw-r--r--lib/talloc/ABI/pytalloc-util.py3-2.1.8.sigs12
-rw-r--r--lib/talloc/ABI/talloc-2.1.6.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.7.sigs65
-rw-r--r--lib/talloc/ABI/talloc-2.1.8.sigs65
-rw-r--r--lib/talloc/pytalloc.c86
-rw-r--r--lib/talloc/pytalloc.h23
-rw-r--r--lib/talloc/pytalloc_guide.txt42
-rw-r--r--lib/talloc/pytalloc_private.h26
-rw-r--r--lib/talloc/pytalloc_util.c199
-rw-r--r--lib/talloc/talloc.c253
-rwxr-xr-xlib/talloc/test_magic_differs.sh10
-rw-r--r--lib/talloc/test_pytalloc.c83
-rw-r--r--lib/talloc/test_pytalloc.py73
-rw-r--r--lib/talloc/testsuite.c76
-rw-r--r--lib/talloc/wscript7
-rw-r--r--lib/tdb/ABI/tdb-1.3.10.sigs69
-rw-r--r--lib/tdb/ABI/tdb-1.3.11.sigs70
-rw-r--r--lib/tdb/ABI/tdb-1.3.12.sigs70
-rw-r--r--lib/tdb/ABI/tdb-1.3.9.sigs69
-rw-r--r--lib/tdb/common/mutex.c138
-rw-r--r--lib/tdb/common/tdb.c227
-rw-r--r--lib/tdb/common/tdb_private.h5
-rw-r--r--lib/tdb/common/traverse.c46
-rw-r--r--lib/tdb/include/tdb.h26
-rw-r--r--lib/tdb/test/external-agent.c3
-rw-r--r--lib/tdb/tools/tdbdump.c3
-rw-r--r--lib/tdb/tools/tdbtorture.c14
-rw-r--r--lib/tdb/wscript2
-rw-r--r--lib/tevent/ABI/tevent-0.9.28.sigs90
-rw-r--r--lib/tevent/ABI/tevent-0.9.29.sigs90
-rw-r--r--lib/tevent/ABI/tevent-0.9.30.sigs96
-rw-r--r--lib/tevent/ABI/tevent-0.9.31.sigs99
-rw-r--r--lib/tevent/doc/tevent_context.dox2
-rw-r--r--lib/tevent/doc/tevent_queue.dox5
-rw-r--r--lib/tevent/doc/tevent_thread.dox4
-rw-r--r--lib/tevent/echo_server.c8
-rw-r--r--lib/tevent/testsuite.c136
-rw-r--r--lib/tevent/tevent.c330
-rw-r--r--lib/tevent/tevent.h105
-rw-r--r--lib/tevent/tevent_epoll.c4
-rw-r--r--lib/tevent/tevent_internal.h51
-rw-r--r--lib/tevent/tevent_poll.c9
-rw-r--r--lib/tevent/tevent_port.c4
-rw-r--r--lib/tevent/tevent_queue.c2
-rw-r--r--lib/tevent/tevent_req.c39
-rw-r--r--lib/tevent/tevent_select.c4
-rw-r--r--lib/tevent/tevent_signal.c56
-rw-r--r--lib/tevent/tevent_standard.c10
-rw-r--r--lib/tevent/tevent_threads.c160
-rw-r--r--lib/tevent/tevent_timed.c88
-rwxr-xr-xlib/tevent/wscript8
-rw-r--r--modules/paged_results.c4
-rw-r--r--modules/rdn_name.c155
-rw-r--r--modules/sort.c46
-rw-r--r--pyldb.h12
-rw-r--r--tests/test-tdb-features.sh13
-rw-r--r--tools/ldbdump.c3
-rw-r--r--tools/ldbutil.h2
-rwxr-xr-xwscript2
99 files changed, 4980 insertions, 837 deletions
diff --git a/ABI/ldb-1.1.27.sigs b/ABI/ldb-1.1.27.sigs
new file mode 100644
index 0000000..4fa30d8
--- /dev/null
+++ b/ABI/ldb-1.1.27.sigs
@@ -0,0 +1,266 @@
+ldb_add: int (struct ldb_context *, const struct ldb_message *)
+ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *)
+ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...)
+ldb_attr_casefold: char *(TALLOC_CTX *, const char *)
+ldb_attr_dn: int (const char *)
+ldb_attr_in_list: int (const char * const *, const char *)
+ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *)
+ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *)
+ldb_base64_decode: int (char *)
+ldb_base64_encode: char *(TALLOC_CTX *, const char *, int)
+ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *)
+ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val)
+ldb_binary_encode_string: char *(TALLOC_CTX *, const char *)
+ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t)
+ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t)
+ldb_check_critical_controls: int (struct ldb_control **)
+ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
+ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
+ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **)
+ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *)
+ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *)
+ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
+ldb_debug_add: void (struct ldb_context *, const char *, ...)
+ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level)
+ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
+ldb_delete: int (struct ldb_context *, struct ldb_dn *)
+ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...)
+ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...)
+ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *)
+ldb_dn_check_special: bool (struct ldb_dn *, const char *)
+ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val)
+ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *)
+ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *)
+ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *)
+ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *)
+ldb_dn_get_casefold: const char *(struct ldb_dn *)
+ldb_dn_get_comp_num: int (struct ldb_dn *)
+ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int)
+ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int)
+ldb_dn_get_extended_comp_num: int (struct ldb_dn *)
+ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *)
+ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int)
+ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *)
+ldb_dn_get_linearized: const char *(struct ldb_dn *)
+ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_get_rdn_name: const char *(struct ldb_dn *)
+ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *)
+ldb_dn_has_extended: bool (struct ldb_dn *)
+ldb_dn_is_null: bool (struct ldb_dn *)
+ldb_dn_is_special: bool (struct ldb_dn *)
+ldb_dn_is_valid: bool (struct ldb_dn *)
+ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_minimise: bool (struct ldb_dn *)
+ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *)
+ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...)
+ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int)
+ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int)
+ldb_dn_remove_extended_components: void (struct ldb_dn *)
+ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val)
+ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *)
+ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *)
+ldb_dn_validate: bool (struct ldb_dn *)
+ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *)
+ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int)
+ldb_errstring: const char *(struct ldb_context *)
+ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **)
+ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *)
+ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_create_perms: unsigned int (struct ldb_context *)
+ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_event_context: struct tevent_context *(struct ldb_context *)
+ldb_get_flags: unsigned int (struct ldb_context *)
+ldb_get_opaque: void *(struct ldb_context *, const char *)
+ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_global_init: int (void)
+ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *)
+ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
+ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
+ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *)
+ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *)
+ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **)
+ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *)
+ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *)
+ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *)
+ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *)
+ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **)
+ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *)
+ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *)
+ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
+ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
+ldb_load_modules: int (struct ldb_context *, const char **)
+ldb_map_add: int (struct ldb_module *, struct ldb_request *)
+ldb_map_delete: int (struct ldb_module *, struct ldb_request *)
+ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *)
+ldb_map_modify: int (struct ldb_module *, struct ldb_request *)
+ldb_map_rename: int (struct ldb_module *, struct ldb_request *)
+ldb_map_search: int (struct ldb_module *, struct ldb_request *)
+ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope)
+ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *)
+ldb_match_msg_objectclass: int (const struct ldb_message *, const char *)
+ldb_mod_register_control: int (struct ldb_module *, const char *)
+ldb_modify: int (struct ldb_context *, const struct ldb_message *)
+ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *)
+ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **)
+ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int)
+ldb_module_flags: uint32_t (struct ldb_context *)
+ldb_module_get_ctx: struct ldb_context *(struct ldb_module *)
+ldb_module_get_name: const char *(struct ldb_module *)
+ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *)
+ldb_module_get_private: void *(struct ldb_module *)
+ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *)
+ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **)
+ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *)
+ldb_module_next: struct ldb_module *(struct ldb_module *)
+ldb_module_popt_options: struct poptOption **(struct ldb_context *)
+ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **)
+ldb_module_send_referral: int (struct ldb_request *, char *)
+ldb_module_set_next: void (struct ldb_module *, struct ldb_module *)
+ldb_module_set_private: void (struct ldb_module *, void *)
+ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type)
+ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *)
+ldb_modules_load: int (const char *, const char *)
+ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int)
+ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **)
+ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...)
+ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *)
+ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *)
+ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *)
+ldb_msg_add_string: int (struct ldb_message *, const char *, const char *)
+ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **)
+ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *)
+ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *)
+ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
+ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *)
+ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
+ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *)
+ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **)
+ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *)
+ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int)
+ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *)
+ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double)
+ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int)
+ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t)
+ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *)
+ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int)
+ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t)
+ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *)
+ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *)
+ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *)
+ldb_msg_new: struct ldb_message *(TALLOC_CTX *)
+ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **)
+ldb_msg_remove_attr: void (struct ldb_message *, const char *)
+ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *)
+ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *)
+ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *)
+ldb_msg_sort_elements: void (struct ldb_message *)
+ldb_next_del_trans: int (struct ldb_module *)
+ldb_next_end_trans: int (struct ldb_module *)
+ldb_next_init: int (struct ldb_module *)
+ldb_next_prepare_commit: int (struct ldb_module *)
+ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *)
+ldb_next_request: int (struct ldb_module *, struct ldb_request *)
+ldb_next_start_trans: int (struct ldb_module *)
+ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_options_find: const char *(struct ldb_context *, const char **, const char *)
+ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *)
+ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *)
+ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **)
+ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *)
+ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *)
+ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *)
+ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *)
+ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t)
+ldb_register_backend: int (const char *, ldb_connect_fn, bool)
+ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *)
+ldb_register_hook: int (ldb_hook_fn)
+ldb_register_module: int (const struct ldb_module_ops *)
+ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *)
+ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *)
+ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *)
+ldb_req_get_custom_flags: uint32_t (struct ldb_request *)
+ldb_req_is_untrusted: bool (struct ldb_request *)
+ldb_req_location: const char *(struct ldb_request *)
+ldb_req_mark_trusted: void (struct ldb_request *)
+ldb_req_mark_untrusted: void (struct ldb_request *)
+ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t)
+ldb_req_set_location: void (struct ldb_request *, const char *)
+ldb_request: int (struct ldb_context *, struct ldb_request *)
+ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *)
+ldb_request_done: int (struct ldb_request *, int)
+ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *)
+ldb_request_get_status: int (struct ldb_request *)
+ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *)
+ldb_request_set_state: void (struct ldb_request *, int)
+ldb_reset_err_string: void (struct ldb_context *)
+ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***)
+ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *)
+ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *)
+ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *)
+ldb_schema_attribute_remove: void (struct ldb_context *, const char *)
+ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *)
+ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...)
+ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *)
+ldb_set_create_perms: void (struct ldb_context *, unsigned int)
+ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *)
+ldb_set_debug_stderr: int (struct ldb_context *)
+ldb_set_default_dns: void (struct ldb_context *)
+ldb_set_errstring: void (struct ldb_context *, const char *)
+ldb_set_event_context: void (struct ldb_context *, struct tevent_context *)
+ldb_set_flags: void (struct ldb_context *, unsigned int)
+ldb_set_modules_dir: void (struct ldb_context *, const char *)
+ldb_set_opaque: int (struct ldb_context *, const char *, void *)
+ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int)
+ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *)
+ldb_set_utf8_default: void (struct ldb_context *)
+ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t))
+ldb_setup_wellknown_attributes: int (struct ldb_context *)
+ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *)
+ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *)
+ldb_strerror: const char *(int)
+ldb_string_to_time: time_t (const char *)
+ldb_string_utc_to_time: time_t (const char *)
+ldb_timestring: char *(TALLOC_CTX *, time_t)
+ldb_timestring_utc: char *(TALLOC_CTX *, time_t)
+ldb_transaction_cancel: int (struct ldb_context *)
+ldb_transaction_cancel_noerr: int (struct ldb_context *)
+ldb_transaction_commit: int (struct ldb_context *)
+ldb_transaction_prepare_commit: int (struct ldb_context *)
+ldb_transaction_start: int (struct ldb_context *)
+ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *)
+ldb_unpack_data_only_attr_list: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int *)
+ldb_unpack_data_only_attr_list_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int, unsigned int *)
+ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *)
+ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *)
+ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
+ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
+ldb_val_string_cmp: int (const struct ldb_val *, const char *)
+ldb_val_to_time: int (const struct ldb_val *, time_t *)
+ldb_valid_attr_name: int (const char *)
+ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list)
+ldb_wait: int (struct ldb_handle *, enum ldb_wait_type)
diff --git a/ABI/ldb-1.1.28.sigs b/ABI/ldb-1.1.28.sigs
new file mode 100644
index 0000000..4fa30d8
--- /dev/null
+++ b/ABI/ldb-1.1.28.sigs
@@ -0,0 +1,266 @@
+ldb_add: int (struct ldb_context *, const struct ldb_message *)
+ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *)
+ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...)
+ldb_attr_casefold: char *(TALLOC_CTX *, const char *)
+ldb_attr_dn: int (const char *)
+ldb_attr_in_list: int (const char * const *, const char *)
+ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *)
+ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *)
+ldb_base64_decode: int (char *)
+ldb_base64_encode: char *(TALLOC_CTX *, const char *, int)
+ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *)
+ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val)
+ldb_binary_encode_string: char *(TALLOC_CTX *, const char *)
+ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t)
+ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t)
+ldb_check_critical_controls: int (struct ldb_control **)
+ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
+ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
+ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **)
+ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *)
+ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *)
+ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
+ldb_debug_add: void (struct ldb_context *, const char *, ...)
+ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level)
+ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
+ldb_delete: int (struct ldb_context *, struct ldb_dn *)
+ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...)
+ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...)
+ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *)
+ldb_dn_check_special: bool (struct ldb_dn *, const char *)
+ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val)
+ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *)
+ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *)
+ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *)
+ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *)
+ldb_dn_get_casefold: const char *(struct ldb_dn *)
+ldb_dn_get_comp_num: int (struct ldb_dn *)
+ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int)
+ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int)
+ldb_dn_get_extended_comp_num: int (struct ldb_dn *)
+ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *)
+ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int)
+ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *)
+ldb_dn_get_linearized: const char *(struct ldb_dn *)
+ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_get_rdn_name: const char *(struct ldb_dn *)
+ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *)
+ldb_dn_has_extended: bool (struct ldb_dn *)
+ldb_dn_is_null: bool (struct ldb_dn *)
+ldb_dn_is_special: bool (struct ldb_dn *)
+ldb_dn_is_valid: bool (struct ldb_dn *)
+ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_minimise: bool (struct ldb_dn *)
+ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *)
+ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...)
+ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int)
+ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int)
+ldb_dn_remove_extended_components: void (struct ldb_dn *)
+ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val)
+ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *)
+ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *)
+ldb_dn_validate: bool (struct ldb_dn *)
+ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *)
+ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int)
+ldb_errstring: const char *(struct ldb_context *)
+ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **)
+ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *)
+ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_create_perms: unsigned int (struct ldb_context *)
+ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_event_context: struct tevent_context *(struct ldb_context *)
+ldb_get_flags: unsigned int (struct ldb_context *)
+ldb_get_opaque: void *(struct ldb_context *, const char *)
+ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_global_init: int (void)
+ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *)
+ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
+ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
+ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *)
+ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *)
+ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **)
+ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *)
+ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *)
+ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *)
+ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *)
+ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **)
+ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *)
+ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *)
+ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
+ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
+ldb_load_modules: int (struct ldb_context *, const char **)
+ldb_map_add: int (struct ldb_module *, struct ldb_request *)
+ldb_map_delete: int (struct ldb_module *, struct ldb_request *)
+ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *)
+ldb_map_modify: int (struct ldb_module *, struct ldb_request *)
+ldb_map_rename: int (struct ldb_module *, struct ldb_request *)
+ldb_map_search: int (struct ldb_module *, struct ldb_request *)
+ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope)
+ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *)
+ldb_match_msg_objectclass: int (const struct ldb_message *, const char *)
+ldb_mod_register_control: int (struct ldb_module *, const char *)
+ldb_modify: int (struct ldb_context *, const struct ldb_message *)
+ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *)
+ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **)
+ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int)
+ldb_module_flags: uint32_t (struct ldb_context *)
+ldb_module_get_ctx: struct ldb_context *(struct ldb_module *)
+ldb_module_get_name: const char *(struct ldb_module *)
+ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *)
+ldb_module_get_private: void *(struct ldb_module *)
+ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *)
+ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **)
+ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *)
+ldb_module_next: struct ldb_module *(struct ldb_module *)
+ldb_module_popt_options: struct poptOption **(struct ldb_context *)
+ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **)
+ldb_module_send_referral: int (struct ldb_request *, char *)
+ldb_module_set_next: void (struct ldb_module *, struct ldb_module *)
+ldb_module_set_private: void (struct ldb_module *, void *)
+ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type)
+ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *)
+ldb_modules_load: int (const char *, const char *)
+ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int)
+ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **)
+ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...)
+ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *)
+ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *)
+ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *)
+ldb_msg_add_string: int (struct ldb_message *, const char *, const char *)
+ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **)
+ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *)
+ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *)
+ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
+ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *)
+ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
+ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *)
+ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **)
+ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *)
+ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int)
+ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *)
+ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double)
+ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int)
+ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t)
+ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *)
+ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int)
+ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t)
+ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *)
+ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *)
+ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *)
+ldb_msg_new: struct ldb_message *(TALLOC_CTX *)
+ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **)
+ldb_msg_remove_attr: void (struct ldb_message *, const char *)
+ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *)
+ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *)
+ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *)
+ldb_msg_sort_elements: void (struct ldb_message *)
+ldb_next_del_trans: int (struct ldb_module *)
+ldb_next_end_trans: int (struct ldb_module *)
+ldb_next_init: int (struct ldb_module *)
+ldb_next_prepare_commit: int (struct ldb_module *)
+ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *)
+ldb_next_request: int (struct ldb_module *, struct ldb_request *)
+ldb_next_start_trans: int (struct ldb_module *)
+ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_options_find: const char *(struct ldb_context *, const char **, const char *)
+ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *)
+ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *)
+ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **)
+ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *)
+ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *)
+ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *)
+ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *)
+ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t)
+ldb_register_backend: int (const char *, ldb_connect_fn, bool)
+ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *)
+ldb_register_hook: int (ldb_hook_fn)
+ldb_register_module: int (const struct ldb_module_ops *)
+ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *)
+ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *)
+ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *)
+ldb_req_get_custom_flags: uint32_t (struct ldb_request *)
+ldb_req_is_untrusted: bool (struct ldb_request *)
+ldb_req_location: const char *(struct ldb_request *)
+ldb_req_mark_trusted: void (struct ldb_request *)
+ldb_req_mark_untrusted: void (struct ldb_request *)
+ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t)
+ldb_req_set_location: void (struct ldb_request *, const char *)
+ldb_request: int (struct ldb_context *, struct ldb_request *)
+ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *)
+ldb_request_done: int (struct ldb_request *, int)
+ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *)
+ldb_request_get_status: int (struct ldb_request *)
+ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *)
+ldb_request_set_state: void (struct ldb_request *, int)
+ldb_reset_err_string: void (struct ldb_context *)
+ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***)
+ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *)
+ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *)
+ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *)
+ldb_schema_attribute_remove: void (struct ldb_context *, const char *)
+ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *)
+ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...)
+ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *)
+ldb_set_create_perms: void (struct ldb_context *, unsigned int)
+ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *)
+ldb_set_debug_stderr: int (struct ldb_context *)
+ldb_set_default_dns: void (struct ldb_context *)
+ldb_set_errstring: void (struct ldb_context *, const char *)
+ldb_set_event_context: void (struct ldb_context *, struct tevent_context *)
+ldb_set_flags: void (struct ldb_context *, unsigned int)
+ldb_set_modules_dir: void (struct ldb_context *, const char *)
+ldb_set_opaque: int (struct ldb_context *, const char *, void *)
+ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int)
+ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *)
+ldb_set_utf8_default: void (struct ldb_context *)
+ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t))
+ldb_setup_wellknown_attributes: int (struct ldb_context *)
+ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *)
+ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *)
+ldb_strerror: const char *(int)
+ldb_string_to_time: time_t (const char *)
+ldb_string_utc_to_time: time_t (const char *)
+ldb_timestring: char *(TALLOC_CTX *, time_t)
+ldb_timestring_utc: char *(TALLOC_CTX *, time_t)
+ldb_transaction_cancel: int (struct ldb_context *)
+ldb_transaction_cancel_noerr: int (struct ldb_context *)
+ldb_transaction_commit: int (struct ldb_context *)
+ldb_transaction_prepare_commit: int (struct ldb_context *)
+ldb_transaction_start: int (struct ldb_context *)
+ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *)
+ldb_unpack_data_only_attr_list: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int *)
+ldb_unpack_data_only_attr_list_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int, unsigned int *)
+ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *)
+ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *)
+ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
+ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
+ldb_val_string_cmp: int (const struct ldb_val *, const char *)
+ldb_val_to_time: int (const struct ldb_val *, time_t *)
+ldb_valid_attr_name: int (const char *)
+ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list)
+ldb_wait: int (struct ldb_handle *, enum ldb_wait_type)
diff --git a/ABI/ldb-1.1.29.sigs b/ABI/ldb-1.1.29.sigs
new file mode 100644
index 0000000..0ea968d
--- /dev/null
+++ b/ABI/ldb-1.1.29.sigs
@@ -0,0 +1,268 @@
+ldb_add: int (struct ldb_context *, const struct ldb_message *)
+ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *)
+ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...)
+ldb_attr_casefold: char *(TALLOC_CTX *, const char *)
+ldb_attr_dn: int (const char *)
+ldb_attr_in_list: int (const char * const *, const char *)
+ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *)
+ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *)
+ldb_base64_decode: int (char *)
+ldb_base64_encode: char *(TALLOC_CTX *, const char *, int)
+ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *)
+ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val)
+ldb_binary_encode_string: char *(TALLOC_CTX *, const char *)
+ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t)
+ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t)
+ldb_check_critical_controls: int (struct ldb_control **)
+ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
+ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
+ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **)
+ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *)
+ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *)
+ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
+ldb_debug_add: void (struct ldb_context *, const char *, ...)
+ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level)
+ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
+ldb_delete: int (struct ldb_context *, struct ldb_dn *)
+ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...)
+ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...)
+ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *)
+ldb_dn_check_special: bool (struct ldb_dn *, const char *)
+ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val)
+ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *)
+ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *)
+ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *)
+ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *)
+ldb_dn_get_casefold: const char *(struct ldb_dn *)
+ldb_dn_get_comp_num: int (struct ldb_dn *)
+ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int)
+ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int)
+ldb_dn_get_extended_comp_num: int (struct ldb_dn *)
+ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *)
+ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int)
+ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *)
+ldb_dn_get_linearized: const char *(struct ldb_dn *)
+ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_get_rdn_name: const char *(struct ldb_dn *)
+ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *)
+ldb_dn_has_extended: bool (struct ldb_dn *)
+ldb_dn_is_null: bool (struct ldb_dn *)
+ldb_dn_is_special: bool (struct ldb_dn *)
+ldb_dn_is_valid: bool (struct ldb_dn *)
+ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_minimise: bool (struct ldb_dn *)
+ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *)
+ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...)
+ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int)
+ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int)
+ldb_dn_remove_extended_components: void (struct ldb_dn *)
+ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val)
+ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *)
+ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *)
+ldb_dn_validate: bool (struct ldb_dn *)
+ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *)
+ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int)
+ldb_errstring: const char *(struct ldb_context *)
+ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **)
+ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *)
+ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_create_perms: unsigned int (struct ldb_context *)
+ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_event_context: struct tevent_context *(struct ldb_context *)
+ldb_get_flags: unsigned int (struct ldb_context *)
+ldb_get_opaque: void *(struct ldb_context *, const char *)
+ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_global_init: int (void)
+ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *)
+ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
+ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
+ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *)
+ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *)
+ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **)
+ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *)
+ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *)
+ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *)
+ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *)
+ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **)
+ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *)
+ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *)
+ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
+ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
+ldb_load_modules: int (struct ldb_context *, const char **)
+ldb_map_add: int (struct ldb_module *, struct ldb_request *)
+ldb_map_delete: int (struct ldb_module *, struct ldb_request *)
+ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *)
+ldb_map_modify: int (struct ldb_module *, struct ldb_request *)
+ldb_map_rename: int (struct ldb_module *, struct ldb_request *)
+ldb_map_search: int (struct ldb_module *, struct ldb_request *)
+ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope)
+ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *)
+ldb_match_msg_objectclass: int (const struct ldb_message *, const char *)
+ldb_mod_register_control: int (struct ldb_module *, const char *)
+ldb_modify: int (struct ldb_context *, const struct ldb_message *)
+ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *)
+ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **)
+ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int)
+ldb_module_flags: uint32_t (struct ldb_context *)
+ldb_module_get_ctx: struct ldb_context *(struct ldb_module *)
+ldb_module_get_name: const char *(struct ldb_module *)
+ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *)
+ldb_module_get_private: void *(struct ldb_module *)
+ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *)
+ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **)
+ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *)
+ldb_module_next: struct ldb_module *(struct ldb_module *)
+ldb_module_popt_options: struct poptOption **(struct ldb_context *)
+ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **)
+ldb_module_send_referral: int (struct ldb_request *, char *)
+ldb_module_set_next: void (struct ldb_module *, struct ldb_module *)
+ldb_module_set_private: void (struct ldb_module *, void *)
+ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type)
+ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *)
+ldb_modules_load: int (const char *, const char *)
+ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int)
+ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **)
+ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...)
+ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *)
+ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *)
+ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *)
+ldb_msg_add_string: int (struct ldb_message *, const char *, const char *)
+ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **)
+ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *)
+ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *)
+ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
+ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *)
+ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
+ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *)
+ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **)
+ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *)
+ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int)
+ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *)
+ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double)
+ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int)
+ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t)
+ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *)
+ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int)
+ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t)
+ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *)
+ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *)
+ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *)
+ldb_msg_new: struct ldb_message *(TALLOC_CTX *)
+ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **)
+ldb_msg_remove_attr: void (struct ldb_message *, const char *)
+ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *)
+ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *)
+ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *)
+ldb_msg_sort_elements: void (struct ldb_message *)
+ldb_next_del_trans: int (struct ldb_module *)
+ldb_next_end_trans: int (struct ldb_module *)
+ldb_next_init: int (struct ldb_module *)
+ldb_next_prepare_commit: int (struct ldb_module *)
+ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *)
+ldb_next_request: int (struct ldb_module *, struct ldb_request *)
+ldb_next_start_trans: int (struct ldb_module *)
+ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_options_find: const char *(struct ldb_context *, const char **, const char *)
+ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *)
+ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *)
+ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **)
+ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *)
+ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *)
+ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *)
+ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *)
+ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t)
+ldb_register_backend: int (const char *, ldb_connect_fn, bool)
+ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *)
+ldb_register_hook: int (ldb_hook_fn)
+ldb_register_module: int (const struct ldb_module_ops *)
+ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *)
+ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *)
+ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *)
+ldb_req_get_custom_flags: uint32_t (struct ldb_request *)
+ldb_req_is_untrusted: bool (struct ldb_request *)
+ldb_req_location: const char *(struct ldb_request *)
+ldb_req_mark_trusted: void (struct ldb_request *)
+ldb_req_mark_untrusted: void (struct ldb_request *)
+ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t)
+ldb_req_set_location: void (struct ldb_request *, const char *)
+ldb_request: int (struct ldb_context *, struct ldb_request *)
+ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *)
+ldb_request_done: int (struct ldb_request *, int)
+ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *)
+ldb_request_get_status: int (struct ldb_request *)
+ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *)
+ldb_request_set_state: void (struct ldb_request *, int)
+ldb_reset_err_string: void (struct ldb_context *)
+ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***)
+ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *)
+ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *)
+ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *)
+ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *, const char *, unsigned int, const struct ldb_schema_syntax *, struct ldb_schema_attribute *)
+ldb_schema_attribute_remove: void (struct ldb_context *, const char *)
+ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int)
+ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *)
+ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...)
+ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *)
+ldb_set_create_perms: void (struct ldb_context *, unsigned int)
+ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *)
+ldb_set_debug_stderr: int (struct ldb_context *)
+ldb_set_default_dns: void (struct ldb_context *)
+ldb_set_errstring: void (struct ldb_context *, const char *)
+ldb_set_event_context: void (struct ldb_context *, struct tevent_context *)
+ldb_set_flags: void (struct ldb_context *, unsigned int)
+ldb_set_modules_dir: void (struct ldb_context *, const char *)
+ldb_set_opaque: int (struct ldb_context *, const char *, void *)
+ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int)
+ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *)
+ldb_set_utf8_default: void (struct ldb_context *)
+ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t))
+ldb_setup_wellknown_attributes: int (struct ldb_context *)
+ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *)
+ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *)
+ldb_strerror: const char *(int)
+ldb_string_to_time: time_t (const char *)
+ldb_string_utc_to_time: time_t (const char *)
+ldb_timestring: char *(TALLOC_CTX *, time_t)
+ldb_timestring_utc: char *(TALLOC_CTX *, time_t)
+ldb_transaction_cancel: int (struct ldb_context *)
+ldb_transaction_cancel_noerr: int (struct ldb_context *)
+ldb_transaction_commit: int (struct ldb_context *)
+ldb_transaction_prepare_commit: int (struct ldb_context *)
+ldb_transaction_start: int (struct ldb_context *)
+ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *)
+ldb_unpack_data_only_attr_list: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int *)
+ldb_unpack_data_only_attr_list_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int, unsigned int *)
+ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *)
+ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *)
+ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
+ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
+ldb_val_string_cmp: int (const struct ldb_val *, const char *)
+ldb_val_to_time: int (const struct ldb_val *, time_t *)
+ldb_valid_attr_name: int (const char *)
+ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list)
+ldb_wait: int (struct ldb_handle *, enum ldb_wait_type)
diff --git a/ABI/pyldb-util-1.1.27.sigs b/ABI/pyldb-util-1.1.27.sigs
new file mode 100644
index 0000000..74d6719
--- /dev/null
+++ b/ABI/pyldb-util-1.1.27.sigs
@@ -0,0 +1,2 @@
+pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
+pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
diff --git a/ABI/pyldb-util-1.1.28.sigs b/ABI/pyldb-util-1.1.28.sigs
new file mode 100644
index 0000000..74d6719
--- /dev/null
+++ b/ABI/pyldb-util-1.1.28.sigs
@@ -0,0 +1,2 @@
+pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
+pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
diff --git a/ABI/pyldb-util-1.1.29.sigs b/ABI/pyldb-util-1.1.29.sigs
new file mode 100644
index 0000000..74d6719
--- /dev/null
+++ b/ABI/pyldb-util-1.1.29.sigs
@@ -0,0 +1,2 @@
+pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
+pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
diff --git a/ABI/pyldb-util.py3-1.1.27.sigs b/ABI/pyldb-util.py3-1.1.27.sigs
new file mode 100644
index 0000000..74d6719
--- /dev/null
+++ b/ABI/pyldb-util.py3-1.1.27.sigs
@@ -0,0 +1,2 @@
+pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
+pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
diff --git a/ABI/pyldb-util.py3-1.1.28.sigs b/ABI/pyldb-util.py3-1.1.28.sigs
new file mode 100644
index 0000000..74d6719
--- /dev/null
+++ b/ABI/pyldb-util.py3-1.1.28.sigs
@@ -0,0 +1,2 @@
+pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
+pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
diff --git a/ABI/pyldb-util.py3-1.1.29.sigs b/ABI/pyldb-util.py3-1.1.29.sigs
new file mode 100644
index 0000000..74d6719
--- /dev/null
+++ b/ABI/pyldb-util.py3-1.1.29.sigs
@@ -0,0 +1,2 @@
+pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
+pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
diff --git a/buildtools/wafsamba/samba_autoconf.py b/buildtools/wafsamba/samba_autoconf.py
index 09ce218..795d130 100644
--- a/buildtools/wafsamba/samba_autoconf.py
+++ b/buildtools/wafsamba/samba_autoconf.py
@@ -708,6 +708,7 @@ def SAMBA_CONFIG_H(conf, path=None):
testflags=True)
conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True)
+ conf.ADD_CFLAGS('-Werror=format-security -Wformat-security', testflags=True)
# This check is because for ldb_search(), a NULL format string
# is not an error, but some compilers complain about that.
if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], '''
@@ -725,6 +726,7 @@ int main(void) {
if Options.options.picky_developer:
conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Werror -Wno-error=deprecated-declarations', testflags=True)
+ conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=tautological-compare', testflags=True)
if Options.options.fatal_errors:
conf.ADD_CFLAGS('-Wfatal-errors', testflags=True)
diff --git a/buildtools/wafsamba/samba_perl.py b/buildtools/wafsamba/samba_perl.py
index f2f176d..2e9a53a 100644
--- a/buildtools/wafsamba/samba_perl.py
+++ b/buildtools/wafsamba/samba_perl.py
@@ -49,7 +49,8 @@ def SAMBA_CHECK_PERL(conf, mandatory=True, version=(5,0,0)):
conf.env.PERL_LIB_INSTALL_DIR = perl_lib_install_dir
perl_inc = read_perl_config_var('print "@INC"')
- perl_inc.remove('.')
+ if '.' in perl_inc:
+ perl_inc.remove('.')
conf.start_msg("PERL_INC: ")
conf.end_msg("%s" % (perl_inc), 'GREEN')
conf.env.PERL_INC = perl_inc
diff --git a/buildtools/wafsamba/wscript b/buildtools/wafsamba/wscript
index 586cc4b..8802e5a 100755
--- a/buildtools/wafsamba/wscript
+++ b/buildtools/wafsamba/wscript
@@ -402,6 +402,22 @@ def configure(conf):
addmain=False,
msg='Checking for library destructor support')
+ conf.CHECK_CODE('''
+ void test_attribute(void) __attribute__ (());
+
+ void test_attribute(void)
+ {
+ return;
+ }
+
+ int main(void) {
+ return 0;
+ }
+ ''',
+ 'HAVE___ATTRIBUTE__',
+ addmain=False,
+ msg='Checking for __attribute__')
+
if sys.platform.startswith('aix'):
conf.DEFINE('_ALL_SOURCE', 1, add_to_cflags=True)
# Might not be needed if ALL_SOURCE is defined
diff --git a/common/ldb.c b/common/ldb.c
index 0f0f5ab..6067256 100644
--- a/common/ldb.c
+++ b/common/ldb.c
@@ -284,15 +284,17 @@ void ldb_set_errstring(struct ldb_context *ldb, const char *err_string)
void ldb_asprintf_errstring(struct ldb_context *ldb, const char *format, ...)
{
va_list ap;
-
+ char *old_err_string = NULL;
if (ldb->err_string) {
- talloc_free(ldb->err_string);
+ old_err_string = ldb->err_string;
}
va_start(ap, format);
ldb->err_string = talloc_vasprintf(ldb, format, ap);
va_end(ap);
+ TALLOC_FREE(old_err_string);
+
if (ldb->flags & LDB_FLG_ENABLE_TRACING) {
ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_asprintf/set_errstring: %s",
ldb->err_string);
@@ -594,7 +596,9 @@ int ldb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
if ((handle->status != LDB_SUCCESS) &&
(handle->ldb->err_string == NULL)) {
/* if no error string was setup by the backend */
- ldb_asprintf_errstring(handle->ldb, "ldb_wait: %s (%d)",
+ ldb_asprintf_errstring(handle->ldb,
+ "ldb_wait from %s with LDB_ASYNC_DONE: %s (%d)",
+ handle->location,
ldb_strerror(handle->status),
handle->status);
}
@@ -612,19 +616,21 @@ int ldb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
if (ret != 0) {
return ldb_operr(handle->ldb);
}
- if (handle->status != LDB_SUCCESS) {
- if (handle->ldb->err_string == NULL) {
- /*
- * if no error string was setup by the backend
- */
- ldb_asprintf_errstring(handle->ldb,
- "ldb_wait: %s (%d)",
- ldb_strerror(handle->status),
- handle->status);
- }
+ if (handle->status == LDB_SUCCESS) {
+ return LDB_SUCCESS;
+ }
+ if (handle->ldb->err_string != NULL) {
return handle->status;
}
- break;
+ /*
+ * if no error string was setup by the backend
+ */
+ ldb_asprintf_errstring(handle->ldb,
+ "ldb_wait from %s with LDB_WAIT_NONE: %s (%d)",
+ handle->location,
+ ldb_strerror(handle->status),
+ handle->status);
+ return handle->status;
case LDB_WAIT_ALL:
while (handle->state != LDB_ASYNC_DONE) {
@@ -633,32 +639,38 @@ int ldb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
return ldb_operr(handle->ldb);
}
if (handle->status != LDB_SUCCESS) {
- if (handle->ldb->err_string == NULL) {
- /*
- * if no error string was setup by the
- * backend
- */
- ldb_asprintf_errstring(handle->ldb,
- "ldb_wait: %s (%d)",
- ldb_strerror(handle->status),
- handle->status);
+ if (handle->ldb->err_string != NULL) {
+ return handle->status;
}
- return handle->status;
- }
- }
- if (handle->status != LDB_SUCCESS) {
- if (handle->ldb->err_string == NULL) {
/*
- * if no error string was setup by the backend
+ * if no error string was setup by the
+ * backend
*/
ldb_asprintf_errstring(handle->ldb,
- "ldb_wait: %s (%d)",
+ "ldb_wait from %s with "
+ "LDB_WAIT_ALL: %s (%d)",
+ handle->location,
ldb_strerror(handle->status),
handle->status);
+ return handle->status;
}
+ }
+ if (handle->status == LDB_SUCCESS) {
+ return LDB_SUCCESS;
+ }
+ if (handle->ldb->err_string != NULL) {
return handle->status;
}
- break;
+ /*
+ * if no error string was setup by the backend
+ */
+ ldb_asprintf_errstring(handle->ldb,
+ "ldb_wait from %s with LDB_WAIT_ALL,"
+ " LDB_ASYNC_DONE: %s (%d)",
+ handle->location,
+ ldb_strerror(handle->status),
+ handle->status);
+ return handle->status;
}
return LDB_SUCCESS;
diff --git a/common/ldb_attributes.c b/common/ldb_attributes.c
index 767f69c..2021a0b 100644
--- a/common/ldb_attributes.c
+++ b/common/ldb_attributes.c
@@ -32,6 +32,41 @@
#include "ldb_handlers.h"
/*
+ fill in an attribute to the ldb_schema into the supplied buffer
+
+ if flags contains LDB_ATTR_FLAG_ALLOCATED
+ the attribute name string will be copied using
+ talloc_strdup(), otherwise it needs to be a static const
+ string at least with a lifetime longer than the ldb struct!
+
+ the ldb_schema_syntax structure should be a pointer
+ to a static const struct or at least it needs to be
+ a struct with a longer lifetime than the ldb context!
+
+*/
+int ldb_schema_attribute_fill_with_syntax(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ const char *attribute,
+ unsigned flags,
+ const struct ldb_schema_syntax *syntax,
+ struct ldb_schema_attribute *a)
+{
+ a->name = attribute;
+ a->flags = flags;
+ a->syntax = syntax;
+
+ if (a->flags & LDB_ATTR_FLAG_ALLOCATED) {
+ a->name = talloc_strdup(mem_ctx, a->name);
+ if (a->name == NULL) {
+ ldb_oom(ldb);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
add a attribute to the ldb_schema
if flags contains LDB_ATTR_FLAG_ALLOCATED
@@ -216,6 +251,39 @@ void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name)
}
/*
+ remove attributes with a specified flag (eg LDB_ATTR_FLAG_FROM_DB) for this ldb context
+
+ This is to permit correct reloads
+*/
+void ldb_schema_attribute_remove_flagged(struct ldb_context *ldb, unsigned int flag)
+{
+ ptrdiff_t i;
+
+ for (i = 0; i < ldb->schema.num_attributes;) {
+ const struct ldb_schema_attribute *a
+ = &ldb->schema.attributes[i];
+ /* FIXED attributes are never removed */
+ if (a->flags & LDB_ATTR_FLAG_FIXED) {
+ i++;
+ continue;
+ }
+ if ((a->flags & flag) == 0) {
+ i++;
+ continue;
+ }
+ if (a->flags & LDB_ATTR_FLAG_ALLOCATED) {
+ talloc_free(discard_const_p(char, a->name));
+ }
+ if (i < ldb->schema.num_attributes - 1) {
+ memmove(&ldb->schema.attributes[i],
+ a+1, sizeof(*a) * (ldb->schema.num_attributes-(i+1)));
+ }
+
+ ldb->schema.num_attributes--;
+ }
+}
+
+/*
setup a attribute handler using a standard syntax
*/
int ldb_schema_attribute_add(struct ldb_context *ldb,
diff --git a/common/ldb_controls.c b/common/ldb_controls.c
index af056d0..a83768a 100644
--- a/common/ldb_controls.c
+++ b/common/ldb_controls.c
@@ -310,14 +310,22 @@ char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *contr
struct ldb_vlv_resp_control *rep_control = talloc_get_type(control->data,
struct ldb_vlv_resp_control);
- res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%d:%d:%s",
+ char *cookie;
+
+ cookie = ldb_base64_encode(mem_ctx,
+ (char *)rep_control->contextId,
+ rep_control->ctxid_len);
+ if (cookie == NULL) {
+ return NULL;
+ }
+
+ res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%d:%s",
LDB_CONTROL_VLV_RESP_NAME,
control->critical,
rep_control->targetPosition,
rep_control->contentCount,
rep_control->vlv_result,
- rep_control->ctxid_len,
- rep_control->contextId);
+ cookie);
return res;
}
@@ -438,7 +446,6 @@ char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *contr
struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *control_strings)
{
struct ldb_control *ctrl;
- char *error_string = NULL;
if (!(ctrl = talloc(mem_ctx, struct ldb_control))) {
ldb_oom(ldb);
@@ -457,16 +464,27 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
ctxid[0] = '\0';
p = &(control_strings[sizeof(LDB_CONTROL_VLV_REQ_NAME)]);
ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
- if (ret < 5) {
- ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
+ /* We allow 2 ways to encode the GT_EQ case, because the
+ comparison string might contain null bytes or colons, which
+ would break sscanf (or indeed any parsing mechanism). */
+ if (ret == 3) {
+ ret = sscanf(p, "%d:%d:%d:>=%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
+ }
+ if (ret == 3) {
+ int len;
+ ret = sscanf(p, "%d:%d:%d:base64>=%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
+ len = ldb_base64_decode(attr);
+ if (len < 0) {
+ ret = -1;
+ }
}
-
+
if ((ret < 4) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, s = string, o = b64 binary blob");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid VLV control syntax\n"
+ " syntax: crit(b):bc(n):ac(n):"
+ "{os(n):cc(n)|>=val(s)|base64>=val(o)}[:ctxid(o)]\n"
+ " note: b = boolean, n = number, s = string, o = b64 binary blob");
talloc_free(ctrl);
return NULL;
}
@@ -490,8 +508,20 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
control->match.byOffset.contentCount = cc;
}
if (ctxid[0]) {
- control->ctxid_len = ldb_base64_decode(ctxid);
- control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len);
+ int len = ldb_base64_decode(ctxid);
+ if (len < 0) {
+ ldb_set_errstring(ldb,
+ "invalid VLV context_id\n");
+ talloc_free(ctrl);
+ return NULL;
+ }
+ control->ctxid_len = len;
+ control->contextId = talloc_memdup(control, ctxid,
+ control->ctxid_len);
+ if (control->contextId == NULL) {
+ ldb_oom(ldb);
+ return NULL;
+ }
} else {
control->ctxid_len = 0;
control->contextId = NULL;
@@ -507,17 +537,16 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
char cookie[1024];
int crit, max_attrs, ret;
uint32_t flags;
-
+
cookie[0] = '\0';
p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_NAME)]);
ret = sscanf(p, "%d:%u:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
if ((ret < 3) || (crit < 0) || (crit > 1) || (max_attrs < 0)) {
- error_string = talloc_asprintf(mem_ctx, "invalid dirsync control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, o = b64 binary blob");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid dirsync control syntax\n"
+ " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n"
+ " note: b = boolean, n = number, o = b64 binary blob");
talloc_free(ctrl);
return NULL;
}
@@ -535,8 +564,19 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
control->flags = flags;
control->max_attributes = max_attrs;
if (*cookie) {
- control->cookie_len = ldb_base64_decode(cookie);
+ int len = ldb_base64_decode(cookie);
+ if (len < 0) {
+ ldb_set_errstring(ldb,
+ "invalid dirsync cookie\n");
+ talloc_free(ctrl);
+ return NULL;
+ }
+ control->cookie_len = len;
control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
+ if (control->cookie == NULL) {
+ ldb_oom(ldb);
+ return NULL;
+ }
} else {
control->cookie = NULL;
control->cookie_len = 0;
@@ -557,12 +597,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
ret = sscanf(p, "%d:%u:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
if ((ret < 3) || (crit < 0) || (crit > 1) || (max_attrs < 0)) {
- error_string = talloc_asprintf(mem_ctx, "invalid %s control syntax\n",
- LDB_CONTROL_DIRSYNC_EX_NAME);
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, o = b64 binary blob");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid dirsync_ex control syntax\n"
+ " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n"
+ " note: b = boolean, n = number, o = b64 binary blob");
talloc_free(ctrl);
return NULL;
}
@@ -580,8 +618,20 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
control->flags = flags;
control->max_attributes = max_attrs;
if (*cookie) {
- control->cookie_len = ldb_base64_decode(cookie);
+ int len = ldb_base64_decode(cookie);
+ if (len < 0) {
+ ldb_set_errstring(ldb,
+ "invalid dirsync_ex cookie"
+ " (probably too long)\n");
+ talloc_free(ctrl);
+ return NULL;
+ }
+ control->cookie_len = len;
control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
+ if (control->cookie == NULL) {
+ ldb_oom(ldb);
+ return NULL;
+ }
} else {
control->cookie = NULL;
control->cookie_len = 0;
@@ -601,11 +651,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_ASQ_NAME)]);
ret = sscanf(p, "%d:%255[^$]", &crit, attr);
if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
- error_string = talloc_asprintf(mem_ctx, "invalid asq control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):attr(s)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid asq control syntax\n"
+ " syntax: crit(b):attr(s)\n"
+ " note: b = boolean, s = string");
talloc_free(ctrl);
return NULL;
}
@@ -631,14 +680,13 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)[:type(i)]\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean\n");
- error_string = talloc_asprintf_append(error_string, " i = integer\n");
- error_string = talloc_asprintf_append(error_string, " valid values are: 0 - hexadecimal representation\n");
- error_string = talloc_asprintf_append(error_string, " 1 - normal string representation");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid extended_dn control syntax\n"
+ " syntax: crit(b)[:type(i)]\n"
+ " note: b = boolean\n"
+ " i = integer\n"
+ " valid values are: 0 - hexadecimal representation\n"
+ " 1 - normal string representation");
talloc_free(ctrl);
return NULL;
}
@@ -664,11 +712,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_SD_FLAGS_NAME)]);
ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags > 0xF)) {
- error_string = talloc_asprintf(mem_ctx, "invalid sd_flags control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):secinfo_flags(n)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid sd_flags control syntax\n"
+ " syntax: crit(b):secinfo_flags(n)\n"
+ " note: b = boolean, n = number");
talloc_free(ctrl);
return NULL;
}
@@ -691,11 +738,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_SEARCH_OPTIONS_NAME)]);
ret = sscanf(p, "%d:%u", &crit, &search_options);
if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options > 0xF)) {
- error_string = talloc_asprintf(mem_ctx, "invalid search_options control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):search_options(n)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid search_options control syntax\n"
+ " syntax: crit(b):search_options(n)\n"
+ " note: b = boolean, n = number");
talloc_free(ctrl);
return NULL;
}
@@ -716,11 +762,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_BYPASS_OPERATIONAL_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid bypassopreational control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid bypassopreational control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -739,11 +784,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_RELAX_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid relax control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid relax control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -762,11 +806,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_RECALCULATE_SD_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid recalculate_sd control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid recalculate_sd control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -785,11 +828,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_DOMAIN_SCOPE_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid domain_scope control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -804,16 +846,18 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PAGED_RESULTS_NAME) == 0) {
struct ldb_paged_control *control;
const char *p;
+ char cookie[1024];
int crit, size, ret;
-
+
+ cookie[0] = '\0';
p = &(control_strings[sizeof(LDB_CONTROL_PAGED_RESULTS_NAME)]);
- ret = sscanf(p, "%d:%d", &crit, &size);
- if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) {
- error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ret = sscanf(p, "%d:%d:%1023[^$]", &crit, &size, cookie);
+ if ((ret < 2) || (ret > 3) || (crit < 0) || (crit > 1) ||
+ (size < 0)) {
+ ldb_set_errstring(ldb,
+ "invalid paged_results control syntax\n"
+ " syntax: crit(b):size(n)[:cookie(base64)]\n"
+ " note: b = boolean, n = number");
talloc_free(ctrl);
return NULL;
}
@@ -822,8 +866,25 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
ctrl->critical = crit;
control = talloc(ctrl, struct ldb_paged_control);
control->size = size;
- control->cookie = NULL;
- control->cookie_len = 0;
+ if (cookie[0] != '\0') {
+ int len = ldb_base64_decode(cookie);
+ if (len < 0) {
+ ldb_set_errstring(ldb,
+ "invalid paged_results cookie"
+ " (probably too long)\n");
+ talloc_free(ctrl);
+ return NULL;
+ }
+ control->cookie_len = len;
+ control->cookie = talloc_memdup(control, cookie, control->cookie_len);
+ if (control->cookie == NULL) {
+ ldb_oom(ldb);
+ return NULL;
+ }
+ } else {
+ control->cookie = NULL;
+ control->cookie_len = 0;
+ }
ctrl->data = control;
return ctrl;
@@ -841,11 +902,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_SERVER_SORT_NAME)]);
ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
- error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid server_sort control syntax\n"
+ " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n"
+ " note: b = boolean, s = string");
talloc_free(ctrl);
return NULL;
}
@@ -872,11 +932,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_NOTIFICATION_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid notification control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid notification control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -895,11 +954,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_TREE_DELETE_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid tree_delete control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid tree_delete control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -918,11 +976,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DELETED_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid show_deleted control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid show_deleted control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -941,11 +998,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid show_deactivated_link control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid show_deactivated_link control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -964,11 +1020,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_SHOW_RECYCLED_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid show_recycled control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid show_recycled control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -987,11 +1042,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_PERMISSIVE_MODIFY_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid permissive_modify control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -1010,11 +1064,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_REVEAL_INTERNALS_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid reveal_internals control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid reveal_internals control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -1036,11 +1089,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
ret = sscanf(p, "%255[^:]:%d", oid, &crit);
if ((ret != 2) || strlen(oid) == 0 || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid local_oid control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: oid(s):crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid local_oid control syntax\n"
+ " syntax: oid(s):crit(b)\n"
+ " note: b = boolean, s = string");
talloc_free(ctrl);
return NULL;
}
@@ -1064,11 +1116,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_RODC_DCPROMO_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid rodc_join control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid rodc_join control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -1087,11 +1138,10 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
p = &(control_strings[sizeof(LDB_CONTROL_PROVISION_NAME)]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid provision control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid provision control syntax\n"
+ " syntax: crit(b)\n"
+ " note: b = boolean");
talloc_free(ctrl);
return NULL;
}
@@ -1115,13 +1165,12 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO
if ((ret != 3) || (crit < 0) || (crit > 1)) {
ret = sscanf(p, "%d:%d", &crit, &flags);
if ((ret != 2) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid verify_name control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(i)[:gc(s)]\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- error_string = talloc_asprintf_append(error_string, " note: i = integer");
- error_string = talloc_asprintf_append(error_string, " note: s = string");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
+ ldb_set_errstring(ldb,
+ "invalid verify_name control syntax\n"
+ " syntax: crit(b):flags(i)[:gc(s)]\n"
+ " note: b = boolean"
+ " note: i = integer"
+ " note: s = string");
talloc_free(ctrl);
return NULL;
}
diff --git a/common/ldb_dn.c b/common/ldb_dn.c
index b7d2de7..b23ee17 100644
--- a/common/ldb_dn.c
+++ b/common/ldb_dn.c
@@ -54,7 +54,7 @@ struct ldb_dn_component {
struct ldb_dn_ext_component {
- char *name;
+ const char *name;
struct ldb_val value;
};
@@ -171,7 +171,7 @@ struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx,
char *strdn;
va_list ap;
- if ( (! mem_ctx) || (! ldb)) return NULL;
+ if (! ldb) return NULL;
va_start(ap, new_fmt);
strdn = talloc_vasprintf(mem_ctx, new_fmt, ap);
@@ -408,11 +408,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
goto failed;
}
- dn->ext_components[dn->ext_comp_num].name = talloc_strdup(dn->ext_components, ex_name);
- if (!dn->ext_components[dn->ext_comp_num].name) {
- /* ouch */
- goto failed;
- }
+ dn->ext_components[dn->ext_comp_num].name = ext_syntax->name;
ret = ext_syntax->read_fn(dn->ldb, dn->ext_components,
&ex_val, &dn->ext_components[dn->ext_comp_num].value);
if (ret != LDB_SUCCESS) {
@@ -1703,7 +1699,7 @@ bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
*/
bool ldb_dn_replace_components(struct ldb_dn *dn, struct ldb_dn *new_dn)
{
- int i;
+ unsigned int i;
if ( ! ldb_dn_validate(dn) || ! ldb_dn_validate(new_dn)) {
return false;
@@ -1908,11 +1904,11 @@ int ldb_dn_set_component(struct ldb_dn *dn, int num,
return LDB_ERR_OTHER;
}
- if (num >= dn->comp_num) {
+ if (num < 0) {
return LDB_ERR_OTHER;
}
- if (num < 0) {
+ if ((unsigned)num >= dn->comp_num) {
return LDB_ERR_OTHER;
}
@@ -1990,12 +1986,14 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
struct ldb_dn_ext_component *p;
unsigned int i;
struct ldb_val v2;
-
+ const struct ldb_dn_extended_syntax *ext_syntax;
+
if ( ! ldb_dn_validate(dn)) {
return LDB_ERR_OTHER;
}
- if (!ldb_dn_extended_syntax_by_name(dn->ldb, name)) {
+ ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name);
+ if (ext_syntax == NULL) {
/* We don't know how to handle this type of thing */
return LDB_ERR_INVALID_DN_SYNTAX;
}
@@ -2006,10 +2004,8 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
dn->ext_components[i].value =
ldb_val_dup(dn->ext_components, val);
- dn->ext_components[i].name =
- talloc_strdup(dn->ext_components, name);
- if (!dn->ext_components[i].name ||
- !dn->ext_components[i].value.data) {
+ dn->ext_components[i].name = ext_syntax->name;
+ if (!dn->ext_components[i].value.data) {
ldb_dn_mark_invalid(dn);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -2170,7 +2166,6 @@ bool ldb_dn_minimise(struct ldb_dn *dn)
*/
for (i = 1; i < dn->ext_comp_num; i++) {
- LDB_FREE(dn->ext_components[i].name);
LDB_FREE(dn->ext_components[i].value.data);
}
dn->ext_comp_num = 1;
diff --git a/common/ldb_match.c b/common/ldb_match.c
index e83ad63..1415fac 100644
--- a/common/ldb_match.c
+++ b/common/ldb_match.c
@@ -693,9 +693,7 @@ _PRIVATE_ int ldb_register_extended_match_rules(struct ldb_context *ldb)
}
/*
- register a new ldb backend
-
- if override is true, then override any existing backend for this prefix
+ register a new ldb extended matching rule
*/
int ldb_register_extended_match_rule(struct ldb_context *ldb,
const struct ldb_extended_match_rule *rule)
diff --git a/common/ldb_modules.c b/common/ldb_modules.c
index 2105966..62f20af 100644
--- a/common/ldb_modules.c
+++ b/common/ldb_modules.c
@@ -901,7 +901,10 @@ static int ldb_modules_load_path(const char *path, const char *version)
} *loaded;
struct loaded *le;
int dlopen_flags;
+
+#ifdef RTLD_DEEPBIND
bool deepbind_enabled = (getenv("LDB_MODULES_DISABLE_DEEPBIND") == NULL);
+#endif
ret = stat(path, &st);
if (ret != 0) {
@@ -937,13 +940,13 @@ static int ldb_modules_load_path(const char *path, const char *version)
#ifdef RTLD_DEEPBIND
/*
* use deepbind if possible, to avoid issues with different
- * system library varients, for example ldb modules may be linked
+ * system library variants, for example ldb modules may be linked
* against Heimdal while the application may use MIT kerberos.
*
* See the dlopen manpage for details.
*
* One typical user is the bind_dlz module of Samba,
- * but symbol versioniong might be enough...
+ * but symbol versioning might be enough...
*
* We need a way to disable this in order to allow the
* ldb_*ldap modules to work with a preloaded socket wrapper.
diff --git a/common/ldb_pack.c b/common/ldb_pack.c
index 7970b9d..a63dd58 100644
--- a/common/ldb_pack.c
+++ b/common/ldb_pack.c
@@ -185,8 +185,7 @@ static bool ldb_consume_element_data(uint8_t **pp, size_t *premaining)
unsigned int remaining = *premaining;
uint8_t *p = *pp;
uint32_t num_values = pull_uint32(p, 0);
- uint32_t len;
- int j;
+ uint32_t j, len;
p += 4;
if (remaining < 4) {
@@ -211,20 +210,20 @@ static bool ldb_consume_element_data(uint8_t **pp, size_t *premaining)
return true;
}
+
/*
* Unpack a ldb message from a linear buffer in ldb_val
*
* Providing a list of attributes to this function allows selective unpacking.
* Giving a NULL list (or a list_size of 0) unpacks all the attributes.
- *
- * Free with ldb_unpack_data_free()
*/
-int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
- const struct ldb_val *data,
- struct ldb_message *message,
- const char * const *list,
- unsigned int list_size,
- unsigned int *nb_elements_in_db)
+int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
+ const struct ldb_val *data,
+ struct ldb_message *message,
+ const char * const *list,
+ unsigned int list_size,
+ unsigned int flags,
+ unsigned int *nb_elements_in_db)
{
uint8_t *p;
size_t remaining;
@@ -234,6 +233,7 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
unsigned int nelem = 0;
size_t len;
unsigned int found = 0;
+ struct ldb_val *ldb_val_single_array = NULL;
if (list == NULL) {
list_size = 0;
@@ -271,10 +271,14 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
errno = EIO;
goto failed;
}
- message->dn = ldb_dn_new(message, ldb, (char *)p);
- if (message->dn == NULL) {
- errno = ENOMEM;
- goto failed;
+ if (flags & LDB_UNPACK_DATA_FLAG_NO_DN) {
+ message->dn = NULL;
+ } else {
+ message->dn = ldb_dn_new(message, ldb, (char *)p);
+ if (message->dn == NULL) {
+ errno = ENOMEM;
+ goto failed;
+ }
}
/*
* Redundant: by definition, remaining must be more
@@ -310,6 +314,26 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
goto failed;
}
+ /*
+ * In typical use, most values are single-valued. This makes
+ * it quite expensive to allocate an array of ldb_val for each
+ * of these, just to then hold the pointer to the data buffer
+ * (in the LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC we don't
+ * allocate the data). So with
+ * LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC we allocate this ahead
+ * of time and use it for the single values where possible.
+ * (This is used the the normal search case, but not in the
+ * index case because of caller requirements).
+ */
+ if (flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) {
+ ldb_val_single_array = talloc_array(message->elements, struct ldb_val,
+ message->num_elements);
+ if (ldb_val_single_array == NULL) {
+ errno = ENOMEM;
+ goto failed;
+ }
+ }
+
for (i=0;i<message->num_elements;i++) {
const char *attr = NULL;
size_t attr_len;
@@ -344,7 +368,7 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
*/
if (list_size != 0) {
bool keep = false;
- int h;
+ unsigned int h;
/*
* We know that p has a \0 terminator before the
@@ -373,11 +397,15 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
}
}
element = &message->elements[nelem];
- element->name = talloc_memdup(message->elements, attr, attr_len+1);
+ if (flags & LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC) {
+ element->name = attr;
+ } else {
+ element->name = talloc_memdup(message->elements, attr, attr_len+1);
- if (element->name == NULL) {
- errno = ENOMEM;
- goto failed;
+ if (element->name == NULL) {
+ errno = ENOMEM;
+ goto failed;
+ }
}
element->flags = 0;
@@ -389,7 +417,9 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
p += attr_len + 1;
element->num_values = pull_uint32(p, 0);
element->values = NULL;
- if (element->num_values != 0) {
+ if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) && element->num_values == 1) {
+ element->values = &ldb_val_single_array[nelem];
+ } else if (element->num_values != 0) {
element->values = talloc_array(message->elements,
struct ldb_val,
element->num_values);
@@ -422,15 +452,18 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
}
element->values[j].length = len;
- element->values[j].data = talloc_size(element->values, len+1);
- if (element->values[j].data == NULL) {
- errno = ENOMEM;
- goto failed;
+ if (flags & LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC) {
+ element->values[j].data = p + 4;
+ } else {
+ element->values[j].data = talloc_size(element->values, len+1);
+ if (element->values[j].data == NULL) {
+ errno = ENOMEM;
+ goto failed;
+ }
+ memcpy(element->values[j].data, p + 4,
+ len);
+ element->values[j].data[len] = 0;
}
- memcpy(element->values[j].data, p + 4,
- len);
- element->values[j].data[len] = 0;
-
remaining -= len;
p += len+4+1;
}
@@ -463,6 +496,30 @@ failed:
return -1;
}
+/*
+ * Unpack a ldb message from a linear buffer in ldb_val
+ *
+ * Providing a list of attributes to this function allows selective unpacking.
+ * Giving a NULL list (or a list_size of 0) unpacks all the attributes.
+ *
+ * Free with ldb_unpack_data_free()
+ */
+int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
+ const struct ldb_val *data,
+ struct ldb_message *message,
+ const char * const *list,
+ unsigned int list_size,
+ unsigned int *nb_elements_in_db)
+{
+ return ldb_unpack_data_only_attr_list_flags(ldb,
+ data,
+ message,
+ list,
+ list_size,
+ 0,
+ nb_elements_in_db);
+}
+
int ldb_unpack_data(struct ldb_context *ldb,
const struct ldb_val *data,
struct ldb_message *message)
diff --git a/include/ldb.h b/include/ldb.h
index e715b92..397f994 100644
--- a/include/ldb.h
+++ b/include/ldb.h
@@ -427,6 +427,11 @@ const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_c
*/
#define LDB_ATTR_FLAG_FORCE_BASE64_LDIF (1<<5)
+/*
+ * The attribute was loaded from a DB, rather than via the C API
+ */
+#define LDB_ATTR_FLAG_FROM_DB (1<<6)
+
/**
LDAP attribute syntax for a DN
@@ -499,6 +504,13 @@ typedef int (*ldb_qsort_cmp_fn_t) (void *v1, void *v2, void *opaque);
#define LDB_CONTROL_BYPASS_OPERATIONAL_NAME "bypassoperational"
/**
+ OID for recalculate RDN (rdn attribute and 'name') control. This control forces
+ the rdn_name module to the recalculate the rdn and name attributes as if the
+ object was just created.
+*/
+#define LDB_CONTROL_RECALCULATE_RDN_OID "1.3.6.1.4.1.7165.4.3.30"
+
+/**
OID for recalculate SD control. This control force the
dsdb code to recalculate the SD of the object as if the
object was just created.
@@ -849,7 +861,7 @@ struct ldb_vlv_req_control {
} gtOrEq;
} match;
int ctxid_len;
- char *contextId;
+ uint8_t *contextId;
};
struct ldb_vlv_resp_control {
@@ -857,7 +869,7 @@ struct ldb_vlv_resp_control {
int contentCount;
int vlv_result;
int ctxid_len;
- char *contextId;
+ uint8_t *contextId;
};
struct ldb_verify_name_control {
diff --git a/include/ldb_module.h b/include/ldb_module.h
index c6a24d3..833d5a8 100644
--- a/include/ldb_module.h
+++ b/include/ldb_module.h
@@ -390,6 +390,12 @@ int ldb_register_extended_match_rule(struct ldb_context *ldb,
int ldb_pack_data(struct ldb_context *ldb,
const struct ldb_message *message,
struct ldb_val *data);
+/*
+ * Unpack a ldb message from a linear buffer in ldb_val
+ *
+ * Providing a list of attributes to this function allows selective unpacking.
+ * Giving a NULL list (or a list_size of 0) unpacks all the attributes.
+ */
int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
const struct ldb_val *data,
struct ldb_message *message,
@@ -399,5 +405,35 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
int ldb_unpack_data(struct ldb_context *ldb,
const struct ldb_val *data,
struct ldb_message *message);
+/*
+ * Unpack a ldb message from a linear buffer in ldb_val
+ *
+ * Providing a list of attributes to this function allows selective unpacking.
+ * Giving a NULL list (or a list_size of 0) unpacks all the attributes.
+ *
+ * Flags allow control of allocation, so that if
+ * LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC is specified, then data in values are
+ * not allocated, instead they point into the supplier constant buffer.
+ *
+ * If LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC is specified, then values
+ * array are not allocated individually (for single-valued
+ * attributes), instead they point into a single buffer per message.
+ *
+ * LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC is only valid when
+ * LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC is also specified.
+ *
+ * Likewise if LDB_UNPACK_DATA_FLAG_NO_DN is specified, the DN is omitted.
+ */
+int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
+ const struct ldb_val *data,
+ struct ldb_message *message,
+ const char * const *list,
+ unsigned int list_size,
+ unsigned int flags,
+ unsigned int *nb_elements_in_db);
+
+#define LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC 0x0001
+#define LDB_UNPACK_DATA_FLAG_NO_DN 0x0002
+#define LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC 0x0004
#endif
diff --git a/include/ldb_private.h b/include/ldb_private.h
index 26a9d42..644d49c 100644
--- a/include/ldb_private.h
+++ b/include/ldb_private.h
@@ -163,6 +163,18 @@ extern const struct ldb_backend_ops ldb_ldapi_backend_ops;
extern const struct ldb_backend_ops ldb_ldaps_backend_ops;
int ldb_setup_wellknown_attributes(struct ldb_context *ldb);
+/*
+ remove attributes with a specified flag (eg LDB_ATTR_FLAG_FROM_DB) for this ldb context
+
+ This is to permit correct reloads
+*/
+void ldb_schema_attribute_remove_flagged(struct ldb_context *ldb, unsigned int flag);
+int ldb_schema_attribute_fill_with_syntax(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ const char *attribute,
+ unsigned flags,
+ const struct ldb_schema_syntax *syntax,
+ struct ldb_schema_attribute *a);
const char **ldb_subclass_list(struct ldb_context *ldb, const char *classname);
void ldb_subclass_remove(struct ldb_context *ldb, const char *classname);
diff --git a/ldb_map/ldb_map.c b/ldb_map/ldb_map.c
index 66b0059..f2a86fe 100644
--- a/ldb_map/ldb_map.c
+++ b/ldb_map/ldb_map.c
@@ -727,6 +727,7 @@ static void map_objectclass_generate_remote(struct ldb_module *module, const cha
struct ldb_val val;
bool found_extensibleObject = false;
unsigned int i;
+ int ret;
ldb = ldb_module_get_ctx(module);
@@ -774,7 +775,11 @@ static void map_objectclass_generate_remote(struct ldb_module *module, const cha
}
/* Add new objectClass to remote message */
- ldb_msg_add(remote, el, 0);
+ ret = ldb_msg_add(remote, el, 0);
+ if (ret != LDB_SUCCESS) {
+ ldb_oom(ldb);
+ return;
+ }
}
/* Map an objectClass into the local partition. */
diff --git a/ldb_map/ldb_map_outbound.c b/ldb_map/ldb_map_outbound.c
index e755b7e..fd25c36 100644
--- a/ldb_map/ldb_map_outbound.c
+++ b/ldb_map/ldb_map_outbound.c
@@ -190,7 +190,7 @@ static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const c
static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el)
{
struct ldb_message_element *old;
- int j;
+ unsigned j;
old = ldb_msg_find_element(msg, el->name);
/* no local result, add as new element */
diff --git a/ldb_tdb/ldb_cache.c b/ldb_tdb/ldb_cache.c
index 6467af1..5ea09d6 100644
--- a/ldb_tdb/ldb_cache.c
+++ b/ldb_tdb/ldb_cache.c
@@ -56,26 +56,10 @@ static const struct {
*/
static void ltdb_attributes_unload(struct ldb_module *module)
{
- struct ldb_context *ldb;
- void *data = ldb_module_get_private(module);
- struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
- struct ldb_message *msg;
- unsigned int i;
-
- ldb = ldb_module_get_ctx(module);
-
- if (ltdb->cache->attributes == NULL) {
- /* no previously loaded attributes */
- return;
- }
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
- msg = ltdb->cache->attributes;
- for (i=0;i<msg->num_elements;i++) {
- ldb_schema_attribute_remove(ldb, msg->elements[i].name);
- }
+ ldb_schema_attribute_remove_flagged(ldb, LDB_ATTR_FLAG_FROM_DB);
- talloc_free(ltdb->cache->attributes);
- ltdb->cache->attributes = NULL;
}
/*
@@ -102,17 +86,24 @@ static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v)
return 0;
}
+static int ldb_schema_attribute_compare(const void *p1, const void *p2)
+{
+ const struct ldb_schema_attribute *sa1 = (const struct ldb_schema_attribute *)p1;
+ const struct ldb_schema_attribute *sa2 = (const struct ldb_schema_attribute *)p2;
+ return ldb_attr_cmp(sa1->name, sa2->name);
+}
+
/*
register any special handlers from @ATTRIBUTES
*/
static int ltdb_attributes_load(struct ldb_module *module)
{
+ struct ldb_schema_attribute *attrs;
struct ldb_context *ldb;
- void *data = ldb_module_get_private(module);
- struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
- struct ldb_message *msg = ltdb->cache->attributes;
+ struct ldb_message *attrs_msg = NULL;
struct ldb_dn *dn;
unsigned int i;
+ unsigned int num_loaded_attrs = 0;
int r;
ldb = ldb_module_get_ctx(module);
@@ -123,26 +114,57 @@ static int ltdb_attributes_load(struct ldb_module *module)
return 0;
}
+ attrs_msg = ldb_msg_new(module);
+ if (attrs_msg == NULL) {
+ goto failed;
+ }
+
dn = ldb_dn_new(module, ldb, LTDB_ATTRIBUTES);
if (dn == NULL) goto failed;
- r = ltdb_search_dn1(module, dn, msg);
+ r = ltdb_search_dn1(module, dn, attrs_msg,
+ LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
+ |LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC
+ |LDB_UNPACK_DATA_FLAG_NO_DN);
talloc_free(dn);
if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
goto failed;
}
- if (r == LDB_ERR_NO_SUCH_OBJECT) {
+ if (r == LDB_ERR_NO_SUCH_OBJECT || attrs_msg->num_elements == 0) {
+ TALLOC_FREE(attrs_msg);
return 0;
}
+
+ attrs = talloc_array(attrs_msg,
+ struct ldb_schema_attribute,
+ attrs_msg->num_elements
+ + ldb->schema.num_attributes);
+ if (attrs == NULL) {
+ goto failed;
+ }
+
+ memcpy(attrs,
+ ldb->schema.attributes,
+ sizeof(ldb->schema.attributes[0]) * ldb->schema.num_attributes);
+
/* mapping these flags onto ldap 'syntaxes' isn't strictly correct,
but its close enough for now */
- for (i=0;i<msg->num_elements;i++) {
+ for (i=0;i<attrs_msg->num_elements;i++) {
unsigned flags;
const char *syntax;
const struct ldb_schema_syntax *s;
+ const struct ldb_schema_attribute *a =
+ ldb_schema_attribute_by_name(ldb,
+ attrs_msg->elements[i].name);
+ if (a != NULL && a->flags & LDB_ATTR_FLAG_FIXED) {
+ /* Must already be set in the array, and kept */
+ continue;
+ }
- if (ltdb_attributes_flags(&msg->elements[i], &flags) != 0) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'", msg->elements[i].name);
+ if (ltdb_attributes_flags(&attrs_msg->elements[i], &flags) != 0) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "Invalid @ATTRIBUTES element for '%s'",
+ attrs_msg->elements[i].name);
goto failed;
}
switch (flags & ~LTDB_FLAG_HIDDEN) {
@@ -157,27 +179,50 @@ static int ltdb_attributes_load(struct ldb_module *module)
break;
default:
ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Invalid flag combination 0x%x for '%s' in @ATTRIBUTES",
- flags, msg->elements[i].name);
+ "Invalid flag combination 0x%x for '%s' "
+ "in @ATTRIBUTES",
+ flags, attrs_msg->elements[i].name);
goto failed;
}
s = ldb_standard_syntax_by_name(ldb, syntax);
if (s == NULL) {
ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Invalid attribute syntax '%s' for '%s' in @ATTRIBUTES",
- syntax, msg->elements[i].name);
+ "Invalid attribute syntax '%s' for '%s' "
+ "in @ATTRIBUTES",
+ syntax, attrs_msg->elements[i].name);
goto failed;
}
- flags |= LDB_ATTR_FLAG_ALLOCATED;
- if (ldb_schema_attribute_add_with_syntax(ldb, msg->elements[i].name, flags, s) != 0) {
+ flags |= LDB_ATTR_FLAG_ALLOCATED | LDB_ATTR_FLAG_FROM_DB;
+
+ r = ldb_schema_attribute_fill_with_syntax(ldb,
+ attrs,
+ attrs_msg->elements[i].name,
+ flags, s,
+ &attrs[num_loaded_attrs + ldb->schema.num_attributes]);
+ if (r != 0) {
goto failed;
}
+ num_loaded_attrs++;
}
+ attrs = talloc_realloc(attrs_msg,
+ attrs, struct ldb_schema_attribute,
+ num_loaded_attrs + ldb->schema.num_attributes);
+ if (attrs == NULL) {
+ goto failed;
+ }
+ TYPESAFE_QSORT(attrs, num_loaded_attrs + ldb->schema.num_attributes,
+ ldb_schema_attribute_compare);
+ talloc_unlink(ldb, ldb->schema.attributes);
+ ldb->schema.attributes = talloc_steal(ldb, attrs);
+ ldb->schema.num_attributes = num_loaded_attrs + ldb->schema.num_attributes;
+ TALLOC_FREE(attrs_msg);
+
return 0;
failed:
+ TALLOC_FREE(attrs_msg);
return -1;
}
@@ -288,9 +333,7 @@ int ltdb_cache_load(struct ldb_module *module)
ltdb->cache = talloc_zero(ltdb, struct ltdb_cache);
if (ltdb->cache == NULL) goto failed;
ltdb->cache->indexlist = ldb_msg_new(ltdb->cache);
- ltdb->cache->attributes = ldb_msg_new(ltdb->cache);
- if (ltdb->cache->indexlist == NULL ||
- ltdb->cache->attributes == NULL) {
+ if (ltdb->cache->indexlist == NULL) {
goto failed;
}
}
@@ -301,7 +344,7 @@ int ltdb_cache_load(struct ldb_module *module)
baseinfo_dn = ldb_dn_new(baseinfo, ldb, LTDB_BASEINFO);
if (baseinfo_dn == NULL) goto failed;
- r= ltdb_search_dn1(module, baseinfo_dn, baseinfo);
+ r= ltdb_search_dn1(module, baseinfo_dn, baseinfo, 0);
if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
goto failed;
}
@@ -319,7 +362,7 @@ int ltdb_cache_load(struct ldb_module *module)
tdb_transaction_commit(ltdb->tdb);
- if (ltdb_search_dn1(module, baseinfo_dn, baseinfo) != LDB_SUCCESS) {
+ if (ltdb_search_dn1(module, baseinfo_dn, baseinfo, 0) != LDB_SUCCESS) {
goto failed;
}
}
@@ -341,7 +384,7 @@ int ltdb_cache_load(struct ldb_module *module)
options_dn = ldb_dn_new(options, ldb, LTDB_OPTIONS);
if (options_dn == NULL) goto failed;
- r= ltdb_search_dn1(module, options_dn, options);
+ r= ltdb_search_dn1(module, options_dn, options, 0);
if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
goto failed;
}
@@ -360,12 +403,17 @@ int ltdb_cache_load(struct ldb_module *module)
}
talloc_free(ltdb->cache->indexlist);
- ltdb_attributes_unload(module); /* calls internally "talloc_free" */
-
+ /*
+ * ltdb_attributes_unload() calls internally talloc_free() on
+ * any non-fixed elemnts in ldb->schema.attributes.
+ *
+ * NOTE WELL: This is per-ldb, not per module, so overwrites
+ * the handlers across all databases when used under Samba's
+ * partition module.
+ */
+ ltdb_attributes_unload(module);
ltdb->cache->indexlist = ldb_msg_new(ltdb->cache);
- ltdb->cache->attributes = ldb_msg_new(ltdb->cache);
- if (ltdb->cache->indexlist == NULL ||
- ltdb->cache->attributes == NULL) {
+ if (ltdb->cache->indexlist == NULL) {
goto failed;
}
ltdb->cache->one_level_indexes = false;
@@ -374,7 +422,10 @@ int ltdb_cache_load(struct ldb_module *module)
indexlist_dn = ldb_dn_new(module, ldb, LTDB_INDEXLIST);
if (indexlist_dn == NULL) goto failed;
- r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist);
+ r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist,
+ LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
+ |LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC
+ |LDB_UNPACK_DATA_FLAG_NO_DN);
if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
goto failed;
}
@@ -386,6 +437,11 @@ int ltdb_cache_load(struct ldb_module *module)
ltdb->cache->attribute_indexes = true;
}
+ /*
+ * NOTE WELL: This is per-ldb, not per module, so overwrites
+ * the handlers across all databases when used under Samba's
+ * partition module.
+ */
if (ltdb_attributes_load(module) == -1) {
goto failed;
}
diff --git a/ldb_tdb/ldb_index.c b/ldb_tdb/ldb_index.c
index cf21092..53fcde5 100644
--- a/ldb_tdb/ldb_index.c
+++ b/ldb_tdb/ldb_index.c
@@ -105,7 +105,7 @@ static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec
{
struct dn_list *list;
if (rec.dsize != sizeof(void *)) {
- ldb_asprintf_errstring(ldb_module_get_ctx(module),
+ ldb_asprintf_errstring(ldb_module_get_ctx(module),
"Bad data size for idxptr %u", (unsigned)rec.dsize);
return NULL;
}
@@ -115,14 +115,14 @@ static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec
memcpy(&list, rec.dptr, sizeof(void *));
list = talloc_get_type(list, struct dn_list);
if (list == NULL) {
- ldb_asprintf_errstring(ldb_module_get_ctx(module),
- "Bad type '%s' for idxptr",
+ ldb_asprintf_errstring(ldb_module_get_ctx(module),
+ "Bad type '%s' for idxptr",
talloc_get_name(list));
return NULL;
}
if (check_parent && list->dn && talloc_parent(list->dn) != list) {
- ldb_asprintf_errstring(ldb_module_get_ctx(module),
- "Bad parent '%s' for idxptr",
+ ldb_asprintf_errstring(ldb_module_get_ctx(module),
+ "Bad parent '%s' for idxptr",
talloc_get_name(talloc_parent(list->dn)));
return NULL;
}
@@ -130,7 +130,7 @@ static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec
}
/*
- return the @IDX list in an index entry for a dn as a
+ return the @IDX list in an index entry for a dn as a
struct dn_list
*/
static int ltdb_dn_list_load(struct ldb_module *module,
@@ -178,7 +178,9 @@ normal_index:
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = ltdb_search_dn1(module, dn, msg);
+ ret = ltdb_search_dn1(module, dn, msg,
+ LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
+ |LDB_UNPACK_DATA_FLAG_NO_DN);
if (ret != LDB_SUCCESS) {
talloc_free(msg);
return ret;
@@ -192,10 +194,18 @@ normal_index:
return LDB_SUCCESS;
}
- /* we avoid copying the strings by stealing the list */
+ /*
+ * we avoid copying the strings by stealing the list. We have
+ * to steal msg onto el->values (which looks odd) because we
+ * asked for the memory to be allocated on msg, not on each
+ * value with LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC above
+ */
+ talloc_steal(el->values, msg);
list->dn = talloc_steal(list, el->values);
list->count = el->num_values;
+ /* We don't need msg->elements any more */
+ talloc_free(msg->elements);
return LDB_SUCCESS;
}
@@ -203,7 +213,7 @@ normal_index:
/*
save a dn_list into a full @IDX style record
*/
-static int ltdb_dn_list_store_full(struct ldb_module *module, struct ldb_dn *dn,
+static int ltdb_dn_list_store_full(struct ldb_module *module, struct ldb_dn *dn,
struct dn_list *list)
{
struct ldb_message *msg;
@@ -249,7 +259,7 @@ static int ltdb_dn_list_store_full(struct ldb_module *module, struct ldb_dn *dn,
/*
save a dn_list into the database, in either @IDX or internal format
*/
-static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn,
+static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn,
struct dn_list *list)
{
struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
@@ -404,7 +414,7 @@ static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
if (r != LDB_SUCCESS) {
const char *errstr = ldb_errstring(ldb);
- /* canonicalisation can be refused. For example,
+ /* canonicalisation can be refused. For example,
a attribute that takes wildcards will refuse to canonicalise
if the value contains a wildcard */
ldb_asprintf_errstring(ldb, "Failed to create index key for attribute '%s':%s%s%s",
@@ -490,7 +500,7 @@ static int ltdb_index_dn_simple(struct ldb_module *module,
return LDB_ERR_OPERATIONS_ERROR;
}
- /* the attribute is indexed. Pull the list of DNs that match the
+ /* the attribute is indexed. Pull the list of DNs that match the
search criterion */
dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value, NULL);
if (!dn) return LDB_ERR_OPERATIONS_ERROR;
@@ -760,7 +770,7 @@ static int ltdb_index_dn_and(struct ldb_module *module,
!ltdb_index_unique(ldb, subtree->u.equality.attr)) {
continue;
}
-
+
ret = ltdb_index_dn(module, subtree, index_list, list);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
/* 0 && X == 0 */
@@ -773,7 +783,7 @@ static int ltdb_index_dn_and(struct ldb_module *module,
* filtering */
return LDB_SUCCESS;
}
- }
+ }
/* now do a full intersection */
found = false;
@@ -787,7 +797,7 @@ static int ltdb_index_dn_and(struct ldb_module *module,
if (list2 == NULL) {
return ldb_module_oom(module);
}
-
+
ret = ltdb_index_dn(module, subtree, index_list, list2);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
@@ -797,7 +807,7 @@ static int ltdb_index_dn_and(struct ldb_module *module,
talloc_free(list2);
return LDB_ERR_NO_SUCH_OBJECT;
}
-
+
if (ret != LDB_SUCCESS) {
/* this didn't adding anything */
talloc_free(list2);
@@ -813,17 +823,17 @@ static int ltdb_index_dn_and(struct ldb_module *module,
talloc_free(list2);
return LDB_ERR_OPERATIONS_ERROR;
}
-
+
if (list->count == 0) {
list->dn = NULL;
return LDB_ERR_NO_SUCH_OBJECT;
}
-
+
if (list->count < 2) {
/* it isn't worth loading the next part of the tree */
return LDB_SUCCESS;
}
- }
+ }
if (!found) {
/* none of the attributes were indexed */
@@ -832,7 +842,7 @@ static int ltdb_index_dn_and(struct ldb_module *module,
return LDB_SUCCESS;
}
-
+
/*
return a list of matching objects using a one-level index
*/
@@ -916,11 +926,12 @@ static int ltdb_index_dn(struct ldb_module *module,
extracting just the given attributes
*/
static int ltdb_index_filter(const struct dn_list *dn_list,
- struct ltdb_context *ac,
+ struct ltdb_context *ac,
uint32_t *match_count)
{
struct ldb_context *ldb;
struct ldb_message *msg;
+ struct ldb_message *filtered_msg;
unsigned int i;
ldb = ldb_module_get_ctx(ac->module);
@@ -941,7 +952,9 @@ static int ltdb_index_filter(const struct dn_list *dn_list,
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = ltdb_search_dn1(ac->module, dn, msg);
+ ret = ltdb_search_dn1(ac->module, dn, msg,
+ LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC|
+ LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC);
talloc_free(dn);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
/* the record has disappeared? yes, this can happen */
@@ -967,14 +980,15 @@ static int ltdb_index_filter(const struct dn_list *dn_list,
}
/* filter the attributes that the user wants */
- ret = ltdb_filter_attrs(msg, ac->attrs);
+ ret = ltdb_filter_attrs(ac, msg, ac->attrs, &filtered_msg);
+
+ talloc_free(msg);
if (ret == -1) {
- talloc_free(msg);
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = ldb_module_send_entry(ac->req, msg, NULL);
+ ret = ldb_module_send_entry(ac->req, filtered_msg, NULL);
if (ret != LDB_SUCCESS) {
/* Regardless of success or failure, the msg
* is the callbacks responsiblity, and should
@@ -1011,7 +1025,7 @@ static void ltdb_dn_list_remove_duplicates(struct dn_list *list)
new_count++;
}
}
-
+
list->count = new_count;
}
@@ -1027,7 +1041,7 @@ int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
int ret;
/* see if indexing is enabled */
- if (!ltdb->cache->attribute_indexes &&
+ if (!ltdb->cache->attribute_indexes &&
!ltdb->cache->one_level_indexes &&
ac->scope != LDB_SCOPE_BASE) {
/* fallback to a full search */
@@ -1053,7 +1067,7 @@ int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
}
dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data);
dn_list->count = 1;
- break;
+ break;
case LDB_SCOPE_ONELEVEL:
if (!ltdb->cache->one_level_indexes) {
@@ -1108,7 +1122,8 @@ int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
* @return An ldb error code
*/
static int ltdb_index_add1(struct ldb_module *module, const char *dn,
- struct ldb_message_element *el, int v_idx)
+ struct ldb_message_element *el, int v_idx,
+ bool is_new)
{
struct ldb_context *ldb;
struct ldb_dn *dn_key;
@@ -1137,21 +1152,26 @@ static int ltdb_index_add1(struct ldb_module *module, const char *dn,
return ret;
}
- if (ltdb_dn_list_find_str(list, dn) != -1) {
- talloc_free(list);
- return LDB_SUCCESS;
- }
-
if (list->count > 0 &&
a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
talloc_free(list);
ldb_asprintf_errstring(ldb, __location__ ": unique index violation on %s in %s",
el->name, dn);
- return LDB_ERR_ENTRY_ALREADY_EXISTS;
+ return LDB_ERR_ENTRY_ALREADY_EXISTS;
+ }
+
+ /* If we are doing an ADD, then this can not already be in the index,
+ as it was not already in the database, and this has already been
+ checked because the store succeeded */
+ if (! is_new) {
+ if (ltdb_dn_list_find_str(list, dn) != -1) {
+ talloc_free(list);
+ return LDB_SUCCESS;
+ }
}
/* overallocate the list a bit, to reduce the number of
- * realloc trigered copies */
+ * realloc trigered copies */
alloc_len = ((list->count+1)+7) & ~7;
list->dn = talloc_realloc(list, list->dn, struct ldb_val, alloc_len);
if (list->dn == NULL) {
@@ -1173,11 +1193,11 @@ static int ltdb_index_add1(struct ldb_module *module, const char *dn,
add index entries for one elements in a message
*/
static int ltdb_index_add_el(struct ldb_module *module, const char *dn,
- struct ldb_message_element *el)
+ struct ldb_message_element *el, bool is_new)
{
unsigned int i;
for (i = 0; i < el->num_values; i++) {
- int ret = ltdb_index_add1(module, dn, el, i);
+ int ret = ltdb_index_add1(module, dn, el, i, is_new);
if (ret != LDB_SUCCESS) {
return ret;
}
@@ -1190,7 +1210,9 @@ static int ltdb_index_add_el(struct ldb_module *module, const char *dn,
add index entries for all elements in a message
*/
static int ltdb_index_add_all(struct ldb_module *module, const char *dn,
- struct ldb_message_element *elements, int num_el)
+ struct ldb_message_element *elements,
+ unsigned int num_el,
+ bool is_new)
{
struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
unsigned int i;
@@ -1209,7 +1231,7 @@ static int ltdb_index_add_all(struct ldb_module *module, const char *dn,
if (!ltdb_is_indexed(ltdb->cache->indexlist, elements[i].name)) {
continue;
}
- ret = ltdb_index_add_el(module, dn, &elements[i]);
+ ret = ltdb_index_add_el(module, dn, &elements[i], is_new);
if (ret != LDB_SUCCESS) {
struct ldb_context *ldb = ldb_module_get_ctx(module);
ldb_asprintf_errstring(ldb,
@@ -1263,7 +1285,7 @@ static int ltdb_index_onelevel(struct ldb_module *module, const struct ldb_messa
el.num_values = 1;
if (add) {
- ret = ltdb_index_add1(module, dn, &el, 0);
+ ret = ltdb_index_add1(module, dn, &el, 0, add);
} else { /* delete */
ret = ltdb_index_del_value(module, msg->dn, &el, 0);
}
@@ -1277,7 +1299,7 @@ static int ltdb_index_onelevel(struct ldb_module *module, const struct ldb_messa
add the index entries for a new element in a record
The caller guarantees that these element values are not yet indexed
*/
-int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn,
+int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn,
struct ldb_message_element *el)
{
struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
@@ -1287,7 +1309,7 @@ int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn,
if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) {
return LDB_SUCCESS;
}
- return ltdb_index_add_el(module, ldb_dn_get_linearized(dn), el);
+ return ltdb_index_add_el(module, ldb_dn_get_linearized(dn), el, true);
}
/*
@@ -1307,7 +1329,8 @@ int ltdb_index_add_new(struct ldb_module *module, const struct ldb_message *msg)
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements);
+ ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements,
+ true);
if (ret != LDB_SUCCESS) {
return ret;
}
@@ -1368,7 +1391,7 @@ int ltdb_index_del_value(struct ldb_module *module, struct ldb_dn *dn,
if (i == -1) {
/* nothing to delete */
talloc_free(dn_key);
- return LDB_SUCCESS;
+ return LDB_SUCCESS;
}
j = (unsigned int) i;
@@ -1376,7 +1399,12 @@ int ltdb_index_del_value(struct ldb_module *module, struct ldb_dn *dn,
memmove(&list->dn[j], &list->dn[j+1], sizeof(list->dn[0])*(list->count - (j+1)));
}
list->count--;
- list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count);
+ if (list->count == 0) {
+ talloc_free(list->dn);
+ list->dn = NULL;
+ } else {
+ list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count);
+ }
ret = ltdb_dn_list_store(module, dn_key, list);
@@ -1487,7 +1515,7 @@ static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, vo
dn = ldb_dn_from_ldb_val(ltdb, ldb_module_get_ctx(module), &v);
ret = ltdb_dn_list_store(module, dn, &list);
if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb_module_get_ctx(module),
+ ldb_asprintf_errstring(ldb_module_get_ctx(module),
"Unable to store null index for %s\n",
ldb_dn_get_linearized(dn));
talloc_free(dn);
@@ -1511,6 +1539,11 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *
struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
struct ldb_module *module = ctx->module;
struct ldb_message *msg;
+ unsigned int nb_elements_in_db;
+ const struct ldb_val val = {
+ .data = data.dptr,
+ .length = data.dsize,
+ };
const char *dn = NULL;
int ret;
TDB_DATA key2;
@@ -1527,7 +1560,11 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *
return -1;
}
- ret = ldb_unpack_data(ldb, (struct ldb_val *)&data, msg);
+ ret = ldb_unpack_data_only_attr_list_flags(ldb, &val,
+ msg,
+ NULL, 0,
+ LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC,
+ &nb_elements_in_db);
if (ret != 0) {
ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
ldb_dn_get_linearized(msg->dn));
@@ -1566,7 +1603,8 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *
return -1;
}
- ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements);
+ ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements,
+ false);
if (ret != LDB_SUCCESS) {
ctx->error = ret;
diff --git a/ldb_tdb/ldb_search.c b/ldb_tdb/ldb_search.c
index 62a36c7..373855f 100644
--- a/ldb_tdb/ldb_search.c
+++ b/ldb_tdb/ldb_search.c
@@ -238,16 +238,50 @@ static int ltdb_search_base(struct ldb_module *module, struct ldb_dn *dn)
struct ltdb_parse_data_unpack_ctx {
struct ldb_message *msg;
struct ldb_module *module;
+ unsigned int unpack_flags;
};
static int ltdb_parse_data_unpack(TDB_DATA key, TDB_DATA data,
void *private_data)
{
struct ltdb_parse_data_unpack_ctx *ctx = private_data;
-
+ unsigned int nb_elements_in_db;
+ int ret;
struct ldb_context *ldb = ldb_module_get_ctx(ctx->module);
- int ret = ldb_unpack_data(ldb, (struct ldb_val *)&data, ctx->msg);
+ struct ldb_val data_parse = {
+ .data = data.dptr,
+ .length = data.dsize
+ };
+
+ if (ctx->unpack_flags & LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC) {
+ /*
+ * If we got LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
+ * we need at least do a memdup on the whole
+ * data buffer as that may change later
+ * and the caller needs a stable result.
+ */
+ data_parse.data = talloc_memdup(ctx->msg,
+ data.dptr,
+ data.dsize);
+ if (data_parse.data == NULL) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "Unable to allocate data(%d) for %*.*s\n",
+ (int)data.dsize,
+ (int)key.dsize, (int)key.dsize, key.dptr);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ }
+
+ ret = ldb_unpack_data_only_attr_list_flags(ldb, &data_parse,
+ ctx->msg,
+ NULL, 0,
+ ctx->unpack_flags,
+ &nb_elements_in_db);
if (ret == -1) {
+ if (data_parse.data != data.dptr) {
+ talloc_free(data_parse.data);
+ }
+
ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %*.*s\n",
(int)key.dsize, (int)key.dsize, key.dptr);
return LDB_ERR_OPERATIONS_ERROR;
@@ -262,7 +296,8 @@ static int ltdb_parse_data_unpack(TDB_DATA key, TDB_DATA data,
return LDB_ERR_NO_SUCH_OBJECT on record-not-found
and LDB_SUCCESS on success
*/
-int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg)
+int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg,
+ unsigned int unpack_flags)
{
void *data = ldb_module_get_private(module);
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
@@ -270,7 +305,8 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes
TDB_DATA tdb_key;
struct ltdb_parse_data_unpack_ctx ctx = {
.msg = msg,
- .module = module
+ .module = module,
+ .unpack_flags = unpack_flags
};
/* form the key */
@@ -296,12 +332,14 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes
} else if (ret != LDB_SUCCESS) {
return ret;
}
-
- if (!msg->dn) {
- msg->dn = ldb_dn_copy(msg, dn);
- }
- if (!msg->dn) {
- return LDB_ERR_OPERATIONS_ERROR;
+
+ if ((unpack_flags & LDB_UNPACK_DATA_FLAG_NO_DN) == 0) {
+ if (!msg->dn) {
+ msg->dn = ldb_dn_copy(msg, dn);
+ }
+ if (!msg->dn) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
}
return LDB_SUCCESS;
@@ -347,81 +385,144 @@ int ltdb_add_attr_results(struct ldb_module *module,
/*
filter the specified list of attributes from a message
- removing not requested attrs.
+ removing not requested attrs from the new message constructed.
+
+ The reason this makes a new message is that the old one may not be
+ individually allocated, which is what our callers expect.
+
*/
-int ltdb_filter_attrs(struct ldb_message *msg, const char * const *attrs)
+int ltdb_filter_attrs(TALLOC_CTX *mem_ctx,
+ const struct ldb_message *msg, const char * const *attrs,
+ struct ldb_message **filtered_msg)
{
unsigned int i;
- int keep_all = 0;
- struct ldb_message_element *el2;
+ bool keep_all = false;
+ bool add_dn = false;
uint32_t num_elements;
+ uint32_t elements_size;
+ struct ldb_message *msg2;
+
+ msg2 = ldb_msg_new(mem_ctx);
+ if (msg2 == NULL) {
+ goto failed;
+ }
+
+ msg2->dn = ldb_dn_copy(msg2, msg->dn);
+ if (msg2->dn == NULL) {
+ goto failed;
+ }
if (attrs) {
/* check for special attrs */
for (i = 0; attrs[i]; i++) {
- if (strcmp(attrs[i], "*") == 0) {
- keep_all = 1;
+ int cmp = strcmp(attrs[i], "*");
+ if (cmp == 0) {
+ keep_all = true;
break;
}
-
- if (ldb_attr_cmp(attrs[i], "distinguishedName") == 0) {
- if (msg_add_distinguished_name(msg) != 0) {
- return -1;
- }
+ cmp = ldb_attr_cmp(attrs[i], "distinguishedName");
+ if (cmp == 0) {
+ add_dn = true;
}
}
} else {
- keep_all = 1;
+ keep_all = true;
}
-
+
if (keep_all) {
- if (msg_add_distinguished_name(msg) != 0) {
+ add_dn = true;
+ elements_size = msg->num_elements + 1;
+
+ /* Shortcuts for the simple cases */
+ } else if (add_dn && i == 1) {
+ if (msg_add_distinguished_name(msg2) != 0) {
return -1;
}
+ *filtered_msg = msg2;
+ return 0;
+ } else if (i == 0) {
+ *filtered_msg = msg2;
return 0;
- }
- el2 = talloc_array(msg, struct ldb_message_element, msg->num_elements);
- if (el2 == NULL) {
- return -1;
+ /* Otherwise we are copying at most as many element as we have attributes */
+ } else {
+ elements_size = i;
}
+
+ msg2->elements = talloc_array(msg2, struct ldb_message_element,
+ elements_size);
+ if (msg2->elements == NULL) goto failed;
+
num_elements = 0;
for (i = 0; i < msg->num_elements; i++) {
+ struct ldb_message_element *el = &msg->elements[i];
+ struct ldb_message_element *el2 = &msg2->elements[num_elements];
unsigned int j;
- int found = 0;
-
- for (j = 0; attrs[j]; j++) {
- if (ldb_attr_cmp(msg->elements[i].name, attrs[j]) == 0) {
- found = 1;
- break;
+
+ if (keep_all == false) {
+ bool found = false;
+ for (j = 0; attrs[j]; j++) {
+ int cmp = ldb_attr_cmp(el->name, attrs[j]);
+ if (cmp == 0) {
+ found = true;
+ break;
+ }
}
+ if (found == false) {
+ continue;
+ }
+ }
+ *el2 = *el;
+ el2->name = talloc_strdup(msg2->elements, el->name);
+ if (el2->name == NULL) {
+ goto failed;
+ }
+ el2->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
+ if (el2->values == NULL) {
+ goto failed;
}
+ for (j=0;j<el->num_values;j++) {
+ el2->values[j] = ldb_val_dup(el2->values, &el->values[j]);
+ if (el2->values[j].data == NULL && el->values[j].length != 0) {
+ goto failed;
+ }
+ }
+ num_elements++;
- if (found) {
- el2[num_elements] = msg->elements[i];
- talloc_steal(el2, el2[num_elements].name);
- talloc_steal(el2, el2[num_elements].values);
- num_elements++;
+ /* Pidginhole principle: we can't have more elements
+ * than the number of attributes if they are unique in
+ * the DB */
+ if (num_elements > elements_size) {
+ goto failed;
}
}
- talloc_free(msg->elements);
+ msg2->num_elements = num_elements;
- if (num_elements > 0) {
- msg->elements = talloc_realloc(msg, el2, struct ldb_message_element,
- num_elements);
- } else {
- msg->elements = talloc_array(msg, struct ldb_message_element, 0);
- talloc_free(el2);
+ if (add_dn) {
+ if (msg_add_distinguished_name(msg2) != 0) {
+ return -1;
+ }
}
- if (msg->elements == NULL) {
- return -1;
+
+ if (msg2->num_elements > 0) {
+ msg2->elements = talloc_realloc(msg2, msg2->elements,
+ struct ldb_message_element,
+ msg2->num_elements);
+ if (msg2->elements == NULL) {
+ return -1;
+ }
+ } else {
+ talloc_free(msg2->elements);
+ msg2->elements = NULL;
}
- msg->num_elements = num_elements;
+ *filtered_msg = msg2;
return 0;
+failed:
+ return -1;
}
/*
@@ -431,9 +532,14 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi
{
struct ldb_context *ldb;
struct ltdb_context *ac;
- struct ldb_message *msg;
+ struct ldb_message *msg, *filtered_msg;
+ const struct ldb_val val = {
+ .data = data.dptr,
+ .length = data.dsize,
+ };
int ret;
bool matched;
+ unsigned int nb_elements_in_db;
ac = talloc_get_type(state, struct ltdb_context);
ldb = ldb_module_get_ctx(ac->module);
@@ -450,7 +556,12 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi
}
/* unpack the record */
- ret = ldb_unpack_data(ldb, (struct ldb_val *)&data, msg);
+ ret = ldb_unpack_data_only_attr_list_flags(ldb, &val,
+ msg,
+ NULL, 0,
+ LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC|
+ LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC,
+ &nb_elements_in_db);
if (ret == -1) {
talloc_free(msg);
ac->error = LDB_ERR_OPERATIONS_ERROR;
@@ -481,15 +592,15 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi
}
/* filter the attributes that the user wants */
- ret = ltdb_filter_attrs(msg, ac->attrs);
+ ret = ltdb_filter_attrs(ac, msg, ac->attrs, &filtered_msg);
+ talloc_free(msg);
if (ret == -1) {
- talloc_free(msg);
ac->error = LDB_ERR_OPERATIONS_ERROR;
return -1;
}
- ret = ldb_module_send_entry(ac->req, msg, NULL);
+ ret = ldb_module_send_entry(ac->req, filtered_msg, NULL);
if (ret != LDB_SUCCESS) {
ac->request_terminated = true;
/* the callback failed, abort the operation */
diff --git a/ldb_tdb/ldb_tdb.c b/ldb_tdb/ldb_tdb.c
index 8d1fd36..7cc0a2e 100644
--- a/ldb_tdb/ldb_tdb.c
+++ b/ldb_tdb/ldb_tdb.c
@@ -449,7 +449,7 @@ static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn)
/* in case any attribute of the message was indexed, we need
to fetch the old record */
- ret = ltdb_search_dn1(module, dn, msg);
+ ret = ltdb_search_dn1(module, dn, msg, LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC);
if (ret != LDB_SUCCESS) {
/* not finding the old record is an error */
goto done;
@@ -858,14 +858,22 @@ int ltdb_modify_internal(struct ldb_module *module,
goto done;
}
- /* TODO: This is O(n^2) - replace with more efficient check */
- for (j=0; j<el->num_values; j++) {
- if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
- ldb_asprintf_errstring(ldb,
- "attribute '%s': value #%u on '%s' provided more than once",
- el->name, j, ldb_dn_get_linearized(msg2->dn));
- ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
- goto done;
+ /*
+ * We don't need to check this if we have been
+ * pre-screened by the repl_meta_data module
+ * in Samba, or someone else who can claim to
+ * know what they are doing.
+ */
+ if (!(el->flags & LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK)) {
+ /* TODO: This is O(n^2) - replace with more efficient check */
+ for (j=0; j<el->num_values; j++) {
+ if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
+ ldb_asprintf_errstring(ldb,
+ "attribute '%s': value #%u on '%s' provided more than once",
+ el->name, j, ldb_dn_get_linearized(msg2->dn));
+ ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+ goto done;
+ }
}
}
@@ -1025,7 +1033,8 @@ static int ltdb_rename(struct ltdb_context *ctx)
}
/* we need to fetch the old record to re-add under the new name */
- ret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
+ ret = ltdb_search_dn1(module, req->op.rename.olddn, msg,
+ LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC);
if (ret != LDB_SUCCESS) {
/* not finding the old record is an error */
return ret;
@@ -1054,7 +1063,7 @@ static int ltdb_rename(struct ltdb_context *ctx)
talloc_free(tdb_key.dptr);
ldb_asprintf_errstring(ldb_module_get_ctx(module),
"Entry %s already exists",
- ldb_dn_get_linearized(msg->dn));
+ ldb_dn_get_linearized(req->op.rename.newdn));
/* finding the new record already in the DB is an error */
talloc_free(msg);
return LDB_ERR_ENTRY_ALREADY_EXISTS;
@@ -1224,7 +1233,7 @@ static int ltdb_sequence_number(struct ltdb_context *ctx,
goto done;
}
- ret = ltdb_search_dn1(module, dn, msg);
+ ret = ltdb_search_dn1(module, dn, msg, 0);
if (ret != LDB_SUCCESS) {
goto done;
}
diff --git a/ldb_tdb/ldb_tdb.h b/ldb_tdb/ldb_tdb.h
index caa98eb..7caedeb 100644
--- a/ldb_tdb/ldb_tdb.h
+++ b/ldb_tdb/ldb_tdb.h
@@ -18,7 +18,6 @@ struct ltdb_private {
struct ltdb_cache {
struct ldb_message *indexlist;
- struct ldb_message *attributes;
bool one_level_indexes;
bool attribute_indexes;
} *cache;
@@ -101,14 +100,17 @@ int ltdb_index_transaction_cancel(struct ldb_module *module);
int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name,
const struct ldb_val *val);
void ltdb_search_dn1_free(struct ldb_module *module, struct ldb_message *msg);
-int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg);
+int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg,
+ unsigned int unpack_flags);
int ltdb_add_attr_results(struct ldb_module *module,
TALLOC_CTX *mem_ctx,
struct ldb_message *msg,
const char * const attrs[],
unsigned int *count,
struct ldb_message ***res);
-int ltdb_filter_attrs(struct ldb_message *msg, const char * const *attrs);
+int ltdb_filter_attrs(TALLOC_CTX *mem_ctx,
+ const struct ldb_message *msg, const char * const *attrs,
+ struct ldb_message **filtered_msg);
int ltdb_search(struct ltdb_context *ctx);
/* The following definitions come from lib/ldb/ldb_tdb/ldb_tdb.c */
diff --git a/lib/replace/closefrom.c b/lib/replace/closefrom.c
new file mode 100644
index 0000000..a61a80f
--- /dev/null
+++ b/lib/replace/closefrom.c
@@ -0,0 +1,138 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Samba utility functions
+ * Copyright (C) Volker Lendecke 2016
+ *
+ * ** NOTE! The following LGPL license applies to the replace
+ * ** 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
+ * Library 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/>.
+ */
+
+#include "replace.h"
+#include <dirent.h>
+#include <unistd.h>
+#include <limits.h>
+
+static int closefrom_sysconf(int lower)
+{
+ long max_files, fd;
+
+ max_files = sysconf(_SC_OPEN_MAX);
+ if (max_files == -1) {
+ max_files = 65536;
+ }
+
+ for (fd=lower; fd<max_files; fd++) {
+ close(fd);
+ }
+
+ return 0;
+}
+
+static int closefrom_procfs(int lower)
+{
+ DIR *dirp;
+ int dir_fd;
+ struct dirent *dp;
+ int *fds = NULL;
+ size_t num_fds = 0;
+ size_t fd_array_size = 0;
+ size_t i;
+ int ret = ENOMEM;
+
+ dirp = opendir("/proc/self/fd");
+ if (dirp == 0) {
+ return errno;
+ }
+
+ dir_fd = dirfd(dirp);
+ if (dir_fd == -1) {
+ ret = errno;
+ goto fail;
+ }
+
+ while ((dp = readdir(dirp)) != NULL) {
+ char *endptr;
+ unsigned long long fd;
+
+ errno = 0;
+
+ fd = strtoull(dp->d_name, &endptr, 10);
+ if ((fd == 0) && (errno == EINVAL)) {
+ continue;
+ }
+ if ((fd == ULLONG_MAX) && (errno == ERANGE)) {
+ continue;
+ }
+ if (*endptr != '\0') {
+ continue;
+ }
+ if (fd == dir_fd) {
+ continue;
+ }
+ if (fd > INT_MAX) {
+ continue;
+ }
+ if (fd < lower) {
+ continue;
+ }
+
+ if (num_fds >= (fd_array_size / sizeof(int))) {
+ void *tmp;
+
+ if (fd_array_size == 0) {
+ fd_array_size = 16 * sizeof(int);
+ } else {
+ if (fd_array_size + fd_array_size <
+ fd_array_size) {
+ /* overflow */
+ goto fail;
+ }
+ fd_array_size = fd_array_size + fd_array_size;
+ }
+
+ tmp = realloc(fds, fd_array_size);
+ if (tmp == NULL) {
+ goto fail;
+ }
+ fds = tmp;
+ }
+
+ fds[num_fds++] = fd;
+ }
+
+ for (i=0; i<num_fds; i++) {
+ close(fds[i]);
+ }
+
+ ret = 0;
+fail:
+ closedir(dirp);
+ free(fds);
+ return ret;
+}
+
+int rep_closefrom(int lower)
+{
+ int ret;
+
+ ret = closefrom_procfs(lower);
+ if (ret == 0) {
+ return 0;
+ }
+
+ return closefrom_sysconf(lower);
+}
diff --git a/lib/replace/replace.h b/lib/replace/replace.h
index c764d06..c69a069 100644
--- a/lib/replace/replace.h
+++ b/lib/replace/replace.h
@@ -247,6 +247,12 @@ size_t rep_strlcpy(char *d, const char *s, size_t bufsize);
size_t rep_strlcat(char *d, const char *s, size_t bufsize);
#endif
+#ifndef HAVE_CLOSEFROM
+#define closefrom rep_closefrom
+int rep_closefrom(int lower);
+#endif
+
+
#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
#undef HAVE_STRNDUP
#define strndup rep_strndup
@@ -425,7 +431,7 @@ int rep_dlclose(void *handle);
#endif
#ifndef PRINTF_ATTRIBUTE
-#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 )
+#ifdef HAVE___ATTRIBUTE__
/** Use gcc attribute to check printf fns. a1 is the 1-based index of
* the parameter containing the format, and a2 the index of the first
* argument. Note that some gcc 2.x versions don't handle this
@@ -437,7 +443,7 @@ int rep_dlclose(void *handle);
#endif
#ifndef _DEPRECATED_
-#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 )
+#ifdef HAVE___ATTRIBUTE__
#define _DEPRECATED_ __attribute__ ((deprecated))
#else
#define _DEPRECATED_
diff --git a/lib/replace/snprintf.c b/lib/replace/snprintf.c
index 86ba74c..63eb036 100644
--- a/lib/replace/snprintf.c
+++ b/lib/replace/snprintf.c
@@ -804,7 +804,7 @@ static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
{
int signvalue = 0;
unsigned LLONG uvalue;
- char convert[20];
+ char convert[22+1]; /* 64-bit value in octal: 22 digits + \0 */
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
@@ -834,8 +834,8 @@ static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
(caps? "0123456789ABCDEF":"0123456789abcdef")
[uvalue % (unsigned)base ];
uvalue = (uvalue / (unsigned)base );
- } while(uvalue && (place < 20));
- if (place == 20) place--;
+ } while(uvalue && (place < sizeof(convert)));
+ if (place == sizeof(convert)) place--;
convert[place] = 0;
zpadlen = max - place;
diff --git a/lib/replace/system/wait.h b/lib/replace/system/wait.h
index 146c61a..1f5fcd9 100644
--- a/lib/replace/system/wait.h
+++ b/lib/replace/system/wait.h
@@ -49,7 +49,7 @@ typedef int sig_atomic_t;
#endif
#if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
-int rep_waitpid(pid_t pid,int *status,int options)
+int rep_waitpid(pid_t pid,int *status,int options);
#endif
#endif
diff --git a/lib/replace/test/testsuite.c b/lib/replace/test/testsuite.c
index 961b77d..dba545e 100644
--- a/lib/replace/test/testsuite.c
+++ b/lib/replace/test/testsuite.c
@@ -1063,6 +1063,38 @@ static int test_memmem(void)
return true;
}
+static bool test_closefrom(void)
+{
+ int i, fd;
+
+ for (i=0; i<100; i++) {
+ fd = dup(0);
+ if (fd == -1) {
+ perror("dup failed");
+ return false;
+ }
+
+ /* 1000 is just an arbitrarily chosen upper bound */
+
+ if (fd >= 1000) {
+ printf("fd=%d\n", fd);
+ return false;
+ }
+ }
+
+ closefrom(3);
+
+ for (i=3; i<=fd; i++) {
+ off_t off;
+ off = lseek(i, 0, SEEK_CUR);
+ if ((off != (off_t)-1) || (errno != EBADF)) {
+ printf("fd %d not closed\n", i);
+ return false;
+ }
+ }
+
+ return true;
+}
bool torture_local_replace(struct torture_context *ctx)
{
@@ -1113,6 +1145,7 @@ bool torture_local_replace(struct torture_context *ctx)
ret &= test_utime();
ret &= test_utimes();
ret &= test_memmem();
+ ret &= test_closefrom();
return ret;
}
diff --git a/lib/replace/wscript b/lib/replace/wscript
index 37cbbb7..1dfd902 100644
--- a/lib/replace/wscript
+++ b/lib/replace/wscript
@@ -202,23 +202,15 @@ def configure(conf):
# Check for atomic builtins. */
conf.CHECK_CODE('''
- int main(void) {
- int i;
- (void)__sync_fetch_and_add(&i, 1);
- return 0;
- }
+ int i;
+ (void)__sync_fetch_and_add(&i, 1);
''',
'HAVE___SYNC_FETCH_AND_ADD',
msg='Checking for __sync_fetch_and_add compiler builtin')
conf.CHECK_CODE('''
- #include <stdint.h>
- #include <sys/atomic.h>
- int main(void) {
- int32_t i;
- atomic_add_32(&i, 1);
- return 0;
- }
+ int32_t i;
+ atomic_add_32(&i, 1);
''',
'HAVE_ATOMIC_ADD_32',
headers='stdint.h sys/atomic.h',
@@ -265,6 +257,9 @@ def configure(conf):
if not conf.CHECK_FUNCS_IN('setproctitle', 'setproctitle', headers='setproctitle.h'):
conf.CHECK_FUNCS_IN('setproctitle', 'bsd', headers='sys/types.h bsd/unistd.h')
+ if not conf.CHECK_FUNCS('closefrom'):
+ conf.CHECK_FUNCS_IN('closefrom', 'bsd', headers='bsd/unistd.h')
+
conf.CHECK_CODE('''
struct ucred cred;
socklen_t cred_len;
@@ -488,6 +483,9 @@ removeea setea
if conf.CONFIG_SET('HAVE_PORT_CREATE') and conf.CONFIG_SET('HAVE_PORT_H'):
conf.DEFINE('HAVE_SOLARIS_PORTS', 1)
+ if conf.CHECK_FUNCS('eventfd', headers='sys/eventfd.h'):
+ conf.DEFINE('HAVE_EVENTFD', 1)
+
conf.CHECK_HEADERS('poll.h')
conf.CHECK_FUNCS('poll')
@@ -691,6 +689,9 @@ def build(bld):
if not bld.CONFIG_SET('HAVE_GETXATTR') or bld.CONFIG_SET('XATTR_ADDITIONAL_OPTIONS'):
REPLACE_SOURCE += ' xattr.c'
+ if not bld.CONFIG_SET('HAVE_CLOSEFROM'):
+ REPLACE_SOURCE += ' closefrom.c'
+
bld.SAMBA_LIBRARY('replace',
source=REPLACE_SOURCE,
group='base_libraries',
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.6.sigs b/lib/talloc/ABI/pytalloc-util-2.1.6.sigs
new file mode 100644
index 0000000..666fec0
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.6.sigs
@@ -0,0 +1,13 @@
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.7.sigs b/lib/talloc/ABI/pytalloc-util-2.1.7.sigs
new file mode 100644
index 0000000..666fec0
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.7.sigs
@@ -0,0 +1,13 @@
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util-2.1.8.sigs b/lib/talloc/ABI/pytalloc-util-2.1.8.sigs
new file mode 100644
index 0000000..666fec0
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.1.8.sigs
@@ -0,0 +1,13 @@
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util.py3-2.1.6.sigs b/lib/talloc/ABI/pytalloc-util.py3-2.1.6.sigs
new file mode 100644
index 0000000..4410f11
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util.py3-2.1.6.sigs
@@ -0,0 +1,12 @@
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util.py3-2.1.7.sigs b/lib/talloc/ABI/pytalloc-util.py3-2.1.7.sigs
new file mode 100644
index 0000000..4410f11
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util.py3-2.1.7.sigs
@@ -0,0 +1,12 @@
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/pytalloc-util.py3-2.1.8.sigs b/lib/talloc/ABI/pytalloc-util.py3-2.1.8.sigs
new file mode 100644
index 0000000..4410f11
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util.py3-2.1.8.sigs
@@ -0,0 +1,12 @@
+_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
+_pytalloc_get_ptr: void *(PyObject *)
+_pytalloc_get_type: void *(PyObject *, const char *)
+pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
+pytalloc_BaseObject_check: int (PyObject *)
+pytalloc_BaseObject_size: size_t (void)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetBaseObjectType: PyTypeObject *(void)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/talloc-2.1.6.sigs b/lib/talloc/ABI/talloc-2.1.6.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.6.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.7.sigs b/lib/talloc/ABI/talloc-2.1.7.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.7.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/ABI/talloc-2.1.8.sigs b/lib/talloc/ABI/talloc-2.1.8.sigs
new file mode 100644
index 0000000..9969ce3
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.1.8.sigs
@@ -0,0 +1,65 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_test_get_magic: int (void)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/pytalloc.c b/lib/talloc/pytalloc.c
index 3afae9c..2039528 100644
--- a/lib/talloc/pytalloc.c
+++ b/lib/talloc/pytalloc.c
@@ -20,6 +20,7 @@
#include <Python.h>
#include <talloc.h>
#include <pytalloc.h>
+#include "pytalloc_private.h"
static PyTypeObject TallocObject_Type;
@@ -157,6 +158,86 @@ static PyTypeObject TallocObject_Type = {
#endif
};
+/**
+ * Default (but only slightly more useful than the default) implementation of Repr().
+ */
+static PyObject *pytalloc_base_default_repr(PyObject *obj)
+{
+ pytalloc_BaseObject *talloc_obj = (pytalloc_BaseObject *)obj;
+ PyTypeObject *type = (PyTypeObject*)PyObject_Type(obj);
+
+ return PyStr_FromFormat("<%s talloc based object at %p>",
+ type->tp_name, talloc_obj->ptr);
+}
+
+/**
+ * Simple dealloc for talloc-wrapping PyObjects
+ */
+static void pytalloc_base_dealloc(PyObject* self)
+{
+ pytalloc_BaseObject *obj = (pytalloc_BaseObject *)self;
+ assert(talloc_unlink(NULL, obj->talloc_ctx) != -1);
+ obj->talloc_ctx = NULL;
+ self->ob_type->tp_free(self);
+}
+
+/**
+ * Default (but only slightly more useful than the default) implementation of cmp.
+ */
+#if PY_MAJOR_VERSION >= 3
+static PyObject *pytalloc_base_default_richcmp(PyObject *obj1, PyObject *obj2, int op)
+{
+ void *ptr1;
+ void *ptr2;
+ if (Py_TYPE(obj1) == Py_TYPE(obj2)) {
+ /* When types match, compare pointers */
+ ptr1 = pytalloc_get_ptr(obj1);
+ ptr2 = pytalloc_get_ptr(obj2);
+ } else if (PyObject_TypeCheck(obj2, &TallocObject_Type)) {
+ /* Otherwise, compare types */
+ ptr1 = Py_TYPE(obj1);
+ ptr2 = Py_TYPE(obj2);
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ switch (op) {
+ case Py_EQ: return PyBool_FromLong(ptr1 == ptr2);
+ case Py_NE: return PyBool_FromLong(ptr1 != ptr2);
+ case Py_LT: return PyBool_FromLong(ptr1 < ptr2);
+ case Py_GT: return PyBool_FromLong(ptr1 > ptr2);
+ case Py_LE: return PyBool_FromLong(ptr1 <= ptr2);
+ case Py_GE: return PyBool_FromLong(ptr1 >= ptr2);
+ }
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+}
+#else
+static int pytalloc_base_default_cmp(PyObject *_obj1, PyObject *_obj2)
+{
+ pytalloc_BaseObject *obj1 = (pytalloc_BaseObject *)_obj1,
+ *obj2 = (pytalloc_BaseObject *)_obj2;
+ if (obj1->ob_type != obj2->ob_type)
+ return ((char *)obj1->ob_type - (char *)obj2->ob_type);
+
+ return ((char *)pytalloc_get_ptr(obj1) - (char *)pytalloc_get_ptr(obj2));
+}
+#endif
+
+static PyTypeObject TallocBaseObject_Type = {
+ .tp_name = "talloc.BaseObject",
+ .tp_doc = "Python wrapper for a talloc-maintained object.",
+ .tp_basicsize = sizeof(pytalloc_BaseObject),
+ .tp_dealloc = (destructor)pytalloc_base_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_repr = pytalloc_base_default_repr,
+#if PY_MAJOR_VERSION >= 3
+ .tp_richcompare = pytalloc_base_default_richcmp,
+#else
+ .tp_compare = pytalloc_base_default_cmp,
+#endif
+};
+
#define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.")
#if PY_MAJOR_VERSION >= 3
@@ -177,6 +258,9 @@ static PyObject *module_init(void)
if (PyType_Ready(&TallocObject_Type) < 0)
return NULL;
+ if (PyType_Ready(&TallocBaseObject_Type) < 0)
+ return NULL;
+
#if PY_MAJOR_VERSION >= 3
m = PyModule_Create(&moduledef);
#else
@@ -187,6 +271,8 @@ static PyObject *module_init(void)
Py_INCREF(&TallocObject_Type);
PyModule_AddObject(m, "Object", (PyObject *)&TallocObject_Type);
+ Py_INCREF(&TallocBaseObject_Type);
+ PyModule_AddObject(m, "BaseObject", (PyObject *)&TallocBaseObject_Type);
return m;
}
diff --git a/lib/talloc/pytalloc.h b/lib/talloc/pytalloc.h
index 608328e..6a0ac18 100644
--- a/lib/talloc/pytalloc.h
+++ b/lib/talloc/pytalloc.h
@@ -26,24 +26,29 @@
typedef struct {
PyObject_HEAD
TALLOC_CTX *talloc_ctx;
- void *ptr;
+ void *ptr; /* eg the array element */
} pytalloc_Object;
/* Return the PyTypeObject for pytalloc_Object. Returns a new reference. */
PyTypeObject *pytalloc_GetObjectType(void);
+/* Return the PyTypeObject for pytalloc_BaseObject. Returns a new reference. */
+PyTypeObject *pytalloc_GetBaseObjectType(void);
+
/* Check whether a specific object is a talloc Object. */
int pytalloc_Check(PyObject *);
+int pytalloc_BaseObject_check(PyObject *);
+
/* Retrieve the pointer for a pytalloc_object. Like talloc_get_type()
* but for pytalloc_Objects. */
+void *_pytalloc_get_type(PyObject *py_obj, const char *type_name);
+#define pytalloc_get_type(py_obj, type) ((type *)_pytalloc_get_type((PyObject *)(py_obj), #type))
-/* FIXME: Call PyErr_SetString(PyExc_TypeError, "expected " __STR(type) ")
- * when talloc_get_type() returns NULL. */
-#define pytalloc_get_type(py_obj, type) (talloc_get_type(pytalloc_get_ptr(py_obj), type))
-
-#define pytalloc_get_ptr(py_obj) (((pytalloc_Object *)py_obj)->ptr)
-#define pytalloc_get_mem_ctx(py_obj) ((pytalloc_Object *)py_obj)->talloc_ctx
+void *_pytalloc_get_ptr(PyObject *py_obj);
+#define pytalloc_get_ptr(py_obj) _pytalloc_get_ptr((PyObject *)(py_obj))
+TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj);
+#define pytalloc_get_mem_ctx(py_obj) _pytalloc_get_mem_ctx((PyObject *)(py_obj))
PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr);
PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr);
@@ -56,4 +61,8 @@ PyObject *pytalloc_reference_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void
PyObject *pytalloc_CObject_FromTallocPtr(void *);
#endif
+size_t pytalloc_BaseObject_size(void);
+
+int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type);
+
#endif /* _PYTALLOC_H_ */
diff --git a/lib/talloc/pytalloc_guide.txt b/lib/talloc/pytalloc_guide.txt
index 36ae5ff..962d449 100644
--- a/lib/talloc/pytalloc_guide.txt
+++ b/lib/talloc/pytalloc_guide.txt
@@ -29,7 +29,7 @@ Python's PEP3149 ABI tag, for example "pytalloc.cpython34m".
To make a build for Python 3, configure with PYTHON=/usr/bin/python3.
.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-pytalloc_Object
+pytalloc_Object / pytalloc_BaseObject
This is the new base class that all Python objects that wrap talloc pointers
derive from. It is itself a subclass of the "Object" type that all objects
@@ -53,12 +53,31 @@ compares the pointers the object is wrapping rather than the objects
themselves (since there can be multiple objects that wrap the same talloc
pointer).
+It is preferred to use pytalloc_BaseObject as this implementation
+exposes less in the C ABI and correctly supports pointers in C arrays
+in the way needed by PIDL.
+
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
PyTypeObject *pytalloc_GetObjectType(void)
-Obtain a reference to the PyTypeObject for `pytalloc_Object`. The reference
-counter for the object will be incremented, so the caller will have to
-decrement it when it no longer needs it (using `Py_DECREF`).
+Obtain a pointer to the PyTypeObject for `pytalloc_Object`. The
+reference counter for the object will be NOT incremented, so the
+caller MUST NOT decrement it when it no longer needs it (eg by using
+`Py_DECREF`).
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+PyTypeObject *pytalloc_GetBaseObjectType(void)
+
+Obtain a pointer to the PyTypeObject for `pytalloc_BaseObject`. The
+reference counter for the object will be NOT incremented, so the
+caller MUST NOT decrement it when it no longer needs it (eg by using
+`Py_DECREF`).
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type);
+
+Wrapper for PyType_Ready() that will set the correct values into
+the PyTypeObject to create a BaseObject
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-
int pytalloc_Check(PyObject *)
@@ -66,6 +85,12 @@ int pytalloc_Check(PyObject *)
Check whether a specific object is a talloc Object. Returns non-zero if it is
a pytalloc_Object and zero otherwise.
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-
+int pytalloc_BaseObject_Check(PyObject *)
+
+Check whether a specific object is a talloc BaseObject. Returns non-zero if it is
+a pytalloc_BaseObject and zero otherwise.
+
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
type *pytalloc_get_type(PyObject *py_obj, type)
@@ -75,13 +100,14 @@ C type, similar to a type passed to `talloc_get_type`.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
pytalloc_get_ptr(PyObject *py_obj)
-Retrieve the pointer from a `pytalloc_Object` py_obj. There is no
-type checking - use `pytalloc_get_type` if possible.
+Retrieve the pointer from a `pytalloc_Object` or `pytalloc_BaseObject`
+py_obj. There is no type checking - use `pytalloc_get_type` if
+possible.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TALLOC_CTX *pytalloc_get_mem_ctx(PyObject *py_obj)
-Retrieve the talloc context associated with a pytalloc_Object.
+Retrieve the talloc context associated with a pytalloc_Object or pytalloc_BaseObject.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr)
@@ -156,6 +182,8 @@ This enables tracking of the NULL memory context without enabling leak
reporting on exit. Useful for when you want to do your own leak
reporting call via talloc_report_null_full().
+This must be done in the top level script, not an imported module.
+
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
pytalloc_total_blocks(obj?)
diff --git a/lib/talloc/pytalloc_private.h b/lib/talloc/pytalloc_private.h
new file mode 100644
index 0000000..b23cdfc
--- /dev/null
+++ b/lib/talloc/pytalloc_private.h
@@ -0,0 +1,26 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2016
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+typedef struct {
+ PyObject_HEAD
+ TALLOC_CTX *talloc_ctx;
+ TALLOC_CTX *talloc_ptr_ctx; /* eg the start of the array */
+ void *ptr; /* eg the array element */
+} pytalloc_BaseObject;
diff --git a/lib/talloc/pytalloc_util.c b/lib/talloc/pytalloc_util.c
index 0af7c05..cb71dc9 100644
--- a/lib/talloc/pytalloc_util.c
+++ b/lib/talloc/pytalloc_util.c
@@ -22,6 +22,7 @@
#include <talloc.h>
#include "pytalloc.h"
#include <assert.h>
+#include "pytalloc_private.h"
_PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void)
{
@@ -43,23 +44,82 @@ _PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void)
return type;
}
+_PUBLIC_ PyTypeObject *pytalloc_GetBaseObjectType(void)
+{
+ static PyTypeObject *type = NULL;
+ PyObject *mod;
+
+ if (type != NULL) {
+ return type;
+ }
+
+ mod = PyImport_ImportModule("talloc");
+ if (mod == NULL) {
+ return NULL;
+ }
+
+ type = (PyTypeObject *)PyObject_GetAttrString(mod, "BaseObject");
+ Py_DECREF(mod);
+
+ return type;
+}
+
/**
* Import an existing talloc pointer into a Python object.
*/
_PUBLIC_ PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx,
- void *ptr)
+ void *ptr)
{
- pytalloc_Object *ret = (pytalloc_Object *)py_type->tp_alloc(py_type, 0);
- ret->talloc_ctx = talloc_new(NULL);
- if (ret->talloc_ctx == NULL) {
- return NULL;
+ PyTypeObject *BaseObjectType = pytalloc_GetBaseObjectType();
+ PyTypeObject *ObjectType = pytalloc_GetObjectType();
+
+ if (mem_ctx == NULL) {
+ return PyErr_NoMemory();
}
- if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) {
+
+ if (PyType_IsSubtype(py_type, BaseObjectType)) {
+ pytalloc_BaseObject *ret
+ = (pytalloc_BaseObject *)py_type->tp_alloc(py_type, 0);
+
+ ret->talloc_ctx = talloc_new(NULL);
+ if (ret->talloc_ctx == NULL) {
+ return NULL;
+ }
+
+ /*
+ * This allows us to keep multiple references to this object -
+ * we only reference this context, which is per ptr, not the
+ * talloc_ctx, which is per pytalloc_Object
+ */
+ if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) {
+ return NULL;
+ }
+ ret->talloc_ptr_ctx = mem_ctx;
+ talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
+ ret->ptr = ptr;
+ return (PyObject *)ret;
+
+ } else if (PyType_IsSubtype(py_type, ObjectType)) {
+ pytalloc_Object *ret
+ = (pytalloc_Object *)py_type->tp_alloc(py_type, 0);
+
+ ret->talloc_ctx = talloc_new(NULL);
+ if (ret->talloc_ctx == NULL) {
+ return NULL;
+ }
+
+ if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) {
+ return NULL;
+ }
+ talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
+ ret->ptr = ptr;
+ return (PyObject *)ret;
+ } else {
+ PyErr_SetString(PyExc_RuntimeError,
+ "pytalloc_steal_ex() called for object type "
+ "not based on talloc");
return NULL;
}
- talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
- ret->ptr = ptr;
- return (PyObject *)ret;
}
/**
@@ -74,27 +134,57 @@ _PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr)
/**
* Import an existing talloc pointer into a Python object, leaving the
* original parent, and creating a reference to the object in the python
- * object
+ * object.
+ *
+ * We remember the object we hold the reference to (a
+ * possibly-non-talloc pointer), the existing parent (typically the
+ * start of the array) and the new referenced parent. That way we can
+ * cope with the fact that we will have multiple parents, one per time
+ * python sees the object.
*/
-_PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr)
+_PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type,
+ TALLOC_CTX *mem_ctx, void *ptr)
{
- pytalloc_Object *ret;
+ PyTypeObject *BaseObjectType = pytalloc_GetBaseObjectType();
+ PyTypeObject *ObjectType = pytalloc_GetObjectType();
- if (ptr == NULL) {
- Py_RETURN_NONE;
+ if (mem_ctx == NULL) {
+ return PyErr_NoMemory();
}
- ret = (pytalloc_Object *)py_type->tp_alloc(py_type, 0);
- ret->talloc_ctx = talloc_new(NULL);
- if (ret->talloc_ctx == NULL) {
+ if (PyType_IsSubtype(py_type, BaseObjectType)) {
+ pytalloc_BaseObject *ret
+ = (pytalloc_BaseObject *)py_type->tp_alloc(py_type, 0);
+ ret->talloc_ctx = talloc_new(NULL);
+ if (ret->talloc_ctx == NULL) {
+ return NULL;
+ }
+ if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) {
+ return NULL;
+ }
+ talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
+ ret->talloc_ptr_ctx = mem_ctx;
+ ret->ptr = ptr;
+ return (PyObject *)ret;
+ } else if (PyType_IsSubtype(py_type, ObjectType)) {
+ pytalloc_Object *ret
+ = (pytalloc_Object *)py_type->tp_alloc(py_type, 0);
+ ret->talloc_ctx = talloc_new(NULL);
+ if (ret->talloc_ctx == NULL) {
+ return NULL;
+ }
+ if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) {
+ return NULL;
+ }
+ talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
+ ret->ptr = ptr;
+ return (PyObject *)ret;
+ } else {
+ PyErr_SetString(PyExc_RuntimeError,
+ "pytalloc_reference_ex() called for object type "
+ "not based on talloc");
return NULL;
}
- if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) {
- return NULL;
- }
- talloc_set_name_const(ret->talloc_ctx, py_type->tp_name);
- ret->ptr = ptr;
- return (PyObject *)ret;
}
#if PY_MAJOR_VERSION < 3
@@ -120,3 +210,66 @@ _PUBLIC_ int pytalloc_Check(PyObject *obj)
return PyObject_TypeCheck(obj, tp);
}
+
+_PUBLIC_ int pytalloc_BaseObject_check(PyObject *obj)
+{
+ PyTypeObject *tp = pytalloc_GetBaseObjectType();
+
+ return PyObject_TypeCheck(obj, tp);
+}
+
+_PUBLIC_ size_t pytalloc_BaseObject_size(void)
+{
+ return sizeof(pytalloc_BaseObject);
+}
+
+_PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name)
+{
+ void *ptr = _pytalloc_get_ptr(py_obj);
+ void *type_obj = talloc_check_name(ptr, type_name);
+
+ if (type_obj == NULL) {
+ const char *name = talloc_get_name(ptr);
+ PyErr_Format(PyExc_TypeError, "pytalloc: expected %s, got %s",
+ type_name, name);
+ return NULL;
+ }
+
+ return ptr;
+}
+
+_PUBLIC_ void *_pytalloc_get_ptr(PyObject *py_obj)
+{
+ if (pytalloc_BaseObject_check(py_obj)) {
+ return ((pytalloc_BaseObject *)py_obj)->ptr;
+ }
+ if (pytalloc_Check(py_obj)) {
+ return ((pytalloc_Object *)py_obj)->ptr;
+ }
+ return NULL;
+}
+
+_PUBLIC_ TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj)
+{
+ if (pytalloc_BaseObject_check(py_obj)) {
+ return ((pytalloc_BaseObject *)py_obj)->talloc_ptr_ctx;
+ }
+ if (pytalloc_Check(py_obj)) {
+ return ((pytalloc_Object *)py_obj)->talloc_ctx;
+ }
+ return NULL;
+}
+
+_PUBLIC_ int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type)
+{
+ PyTypeObject *talloc_type = pytalloc_GetBaseObjectType();
+ if (talloc_type == NULL) {
+ PyErr_Format(PyExc_TypeError, "pytalloc: unable to get talloc.BaseObject type");
+ return -1;
+ }
+
+ type->tp_base = talloc_type;
+ type->tp_basicsize = pytalloc_BaseObject_size();
+
+ return PyType_Ready(type);
+}
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 90b9d96..279021c 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -80,9 +80,10 @@
#define TALLOC_MAGIC_BASE 0xe814ec70
static unsigned int talloc_magic = (
- TALLOC_MAGIC_BASE +
- (TALLOC_VERSION_MAJOR << 12) +
- (TALLOC_VERSION_MINOR << 4));
+ ~TALLOC_FLAG_MASK & (
+ TALLOC_MAGIC_BASE +
+ (TALLOC_VERSION_MAJOR << 12) +
+ (TALLOC_VERSION_MINOR << 4)));
/* by default we abort when given a bad pointer (such as when talloc_free() is called
on a pointer that came from malloc() */
@@ -250,16 +251,45 @@ static inline void talloc_memlimit_grow(struct talloc_memlimit *limit,
size_t size);
static inline void talloc_memlimit_shrink(struct talloc_memlimit *limit,
size_t size);
-static inline void talloc_memlimit_update_on_free(struct talloc_chunk *tc);
+static inline void tc_memlimit_update_on_free(struct talloc_chunk *tc);
-static inline void _talloc_set_name_const(const void *ptr, const char *name);
+static inline void _tc_set_name_const(struct talloc_chunk *tc,
+ const char *name);
+static struct talloc_chunk *_vasprintf_tc(const void *t,
+ const char *fmt,
+ va_list ap);
typedef int (*talloc_destructor_t)(void *);
struct talloc_pool_hdr;
struct talloc_chunk {
+ /*
+ * flags includes the talloc magic, which is randomised to
+ * make overwrite attacks harder
+ */
unsigned flags;
+
+ /*
+ * If you have a logical tree like:
+ *
+ * <parent>
+ * / | \
+ * / | \
+ * / | \
+ * <child 1> <child 2> <child 3>
+ *
+ * The actual talloc tree is:
+ *
+ * <parent>
+ * |
+ * <child 1> - <child 2> - <child 3>
+ *
+ * The children are linked with next/prev pointers, and
+ * child 1 is linked to the parent with parent/child
+ * pointers.
+ */
+
struct talloc_chunk *next, *prev;
struct talloc_chunk *parent, *child;
struct talloc_reference_handle *refs;
@@ -572,7 +602,7 @@ static inline void tc_invalidate_pool(struct talloc_pool_hdr *pool_hdr)
Allocate from a pool
*/
-static inline struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
+static inline struct talloc_chunk *tc_alloc_pool(struct talloc_chunk *parent,
size_t size, size_t prefix_len)
{
struct talloc_pool_hdr *pool_hdr = NULL;
@@ -625,12 +655,15 @@ static inline struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent
/*
Allocate a bit of memory as a child of an existing pointer
*/
-static inline void *__talloc_with_prefix(const void *context, size_t size,
- size_t prefix_len)
+static inline void *__talloc_with_prefix(const void *context,
+ size_t size,
+ size_t prefix_len,
+ struct talloc_chunk **tc_ret)
{
struct talloc_chunk *tc = NULL;
struct talloc_memlimit *limit = NULL;
size_t total_len = TC_HDR_SIZE + size + prefix_len;
+ struct talloc_chunk *parent = NULL;
if (unlikely(context == NULL)) {
context = null_context;
@@ -644,14 +677,14 @@ static inline void *__talloc_with_prefix(const void *context, size_t size,
return NULL;
}
- if (context != NULL) {
- struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
+ if (likely(context != NULL)) {
+ parent = talloc_chunk_from_ptr(context);
- if (ptc->limit != NULL) {
- limit = ptc->limit;
+ if (parent->limit != NULL) {
+ limit = parent->limit;
}
- tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size, prefix_len);
+ tc = tc_alloc_pool(parent, TC_HDR_SIZE+size, prefix_len);
}
if (tc == NULL) {
@@ -683,9 +716,7 @@ static inline void *__talloc_with_prefix(const void *context, size_t size,
tc->name = NULL;
tc->refs = NULL;
- if (likely(context)) {
- struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
-
+ if (likely(context != NULL)) {
if (parent->child) {
parent->child->parent = NULL;
tc->next = parent->child;
@@ -700,12 +731,15 @@ static inline void *__talloc_with_prefix(const void *context, size_t size,
tc->next = tc->prev = tc->parent = NULL;
}
+ *tc_ret = tc;
return TC_PTR_FROM_CHUNK(tc);
}
-static inline void *__talloc(const void *context, size_t size)
+static inline void *__talloc(const void *context,
+ size_t size,
+ struct talloc_chunk **tc)
{
- return __talloc_with_prefix(context, size, 0);
+ return __talloc_with_prefix(context, size, 0, tc);
}
/*
@@ -718,13 +752,12 @@ static inline void *_talloc_pool(const void *context, size_t size)
struct talloc_pool_hdr *pool_hdr;
void *result;
- result = __talloc_with_prefix(context, size, TP_HDR_SIZE);
+ result = __talloc_with_prefix(context, size, TP_HDR_SIZE, &tc);
if (unlikely(result == NULL)) {
return NULL;
}
- tc = talloc_chunk_from_ptr(result);
pool_hdr = talloc_pool_from_chunk(tc);
tc->flags |= TALLOC_FLAG_POOL;
@@ -803,7 +836,7 @@ _PUBLIC_ void *_talloc_pooled_object(const void *ctx,
pool_hdr->end = ((char *)pool_hdr->end + TC_ALIGN16(type_size));
- _talloc_set_name_const(ret, type_name);
+ _tc_set_name_const(tc, type_name);
return ret;
overflow:
@@ -849,9 +882,9 @@ static int talloc_reference_destructor(struct talloc_reference_handle *handle)
more efficient way to add a name to a pointer - the name must point to a
true string constant
*/
-static inline void _talloc_set_name_const(const void *ptr, const char *name)
+static inline void _tc_set_name_const(struct talloc_chunk *tc,
+ const char *name)
{
- struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
tc->name = name;
}
@@ -861,13 +894,14 @@ static inline void _talloc_set_name_const(const void *ptr, const char *name)
static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
{
void *ptr;
+ struct talloc_chunk *tc;
- ptr = __talloc(context, size);
+ ptr = __talloc(context, size, &tc);
if (unlikely(ptr == NULL)) {
return NULL;
}
- _talloc_set_name_const(ptr, name);
+ _tc_set_name_const(tc, name);
return ptr;
}
@@ -905,7 +939,7 @@ _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const
static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
-static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
+static inline void _tc_free_poolmem(struct talloc_chunk *tc,
const char *location)
{
struct talloc_pool_hdr *pool;
@@ -956,15 +990,15 @@ static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
pool_tc->name = location;
if (pool_tc->flags & TALLOC_FLAG_POOLMEM) {
- _talloc_free_poolmem(pool_tc, location);
+ _tc_free_poolmem(pool_tc, location);
} else {
/*
- * The talloc_memlimit_update_on_free()
+ * The tc_memlimit_update_on_free()
* call takes into account the
* prefix TP_HDR_SIZE allocated before
* the pool talloc_chunk.
*/
- talloc_memlimit_update_on_free(pool_tc);
+ tc_memlimit_update_on_free(pool_tc);
TC_INVALIDATE_FULL_CHUNK(pool_tc);
free(pool);
}
@@ -987,33 +1021,20 @@ static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
*/
}
-static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
+static inline void _tc_free_children_internal(struct talloc_chunk *tc,
void *ptr,
const char *location);
+static inline int _talloc_free_internal(void *ptr, const char *location);
+
/*
- internal talloc_free call
+ internal free call that takes a struct talloc_chunk *.
*/
-static inline int _talloc_free_internal(void *ptr, const char *location)
+static inline int _tc_free_internal(struct talloc_chunk *tc,
+ const char *location)
{
- struct talloc_chunk *tc;
void *ptr_to_free;
-
- if (unlikely(ptr == NULL)) {
- return -1;
- }
-
- /* possibly initialised the talloc fill value */
- if (unlikely(!talloc_fill.initialised)) {
- const char *fill = getenv(TALLOC_FILL_ENV);
- if (fill != NULL) {
- talloc_fill.enabled = true;
- talloc_fill.fill_value = strtoul(fill, NULL, 0);
- }
- talloc_fill.initialised = true;
- }
-
- tc = talloc_chunk_from_ptr(ptr);
+ void *ptr = TC_PTR_FROM_CHUNK(tc);
if (unlikely(tc->refs)) {
int is_child;
@@ -1039,6 +1060,20 @@ static inline int _talloc_free_internal(void *ptr, const char *location)
if (unlikely(tc->destructor)) {
talloc_destructor_t d = tc->destructor;
+
+ /*
+ * Protect the destructor against some overwrite
+ * attacks, by explicitly checking it has the right
+ * magic here.
+ */
+ if (talloc_chunk_from_ptr(ptr) != tc) {
+ /*
+ * This can't actually happen, the
+ * call itself will panic.
+ */
+ TALLOC_ABORT("talloc_chunk_from_ptr failed!");
+ }
+
if (d == (talloc_destructor_t)-1) {
return -1;
}
@@ -1069,7 +1104,7 @@ static inline int _talloc_free_internal(void *ptr, const char *location)
tc->flags |= TALLOC_FLAG_LOOP;
- _talloc_free_children_internal(tc, ptr, location);
+ _tc_free_children_internal(tc, ptr, location);
tc->flags |= TALLOC_FLAG_FREE;
@@ -1106,17 +1141,42 @@ static inline int _talloc_free_internal(void *ptr, const char *location)
}
if (tc->flags & TALLOC_FLAG_POOLMEM) {
- _talloc_free_poolmem(tc, location);
+ _tc_free_poolmem(tc, location);
return 0;
}
- talloc_memlimit_update_on_free(tc);
+ tc_memlimit_update_on_free(tc);
TC_INVALIDATE_FULL_CHUNK(tc);
free(ptr_to_free);
return 0;
}
+/*
+ internal talloc_free call
+*/
+static inline int _talloc_free_internal(void *ptr, const char *location)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return -1;
+ }
+
+ /* possibly initialised the talloc fill value */
+ if (unlikely(!talloc_fill.initialised)) {
+ const char *fill = getenv(TALLOC_FILL_ENV);
+ if (fill != NULL) {
+ talloc_fill.enabled = true;
+ talloc_fill.fill_value = strtoul(fill, NULL, 0);
+ }
+ talloc_fill.initialised = true;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+ return _tc_free_internal(tc, location);
+}
+
static inline size_t _talloc_total_limit_size(const void *ptr,
struct talloc_memlimit *old_limit,
struct talloc_memlimit *new_limit);
@@ -1359,14 +1419,22 @@ _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
/*
add a name to an existing pointer - va_list version
*/
-static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+static inline const char *tc_set_name_v(struct talloc_chunk *tc,
+ const char *fmt,
+ va_list ap) PRINTF_ATTRIBUTE(2,0);
-static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
+static inline const char *tc_set_name_v(struct talloc_chunk *tc,
+ const char *fmt,
+ va_list ap)
{
- struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
- tc->name = talloc_vasprintf(ptr, fmt, ap);
- if (likely(tc->name)) {
- _talloc_set_name_const(tc->name, ".name");
+ struct talloc_chunk *name_tc = _vasprintf_tc(TC_PTR_FROM_CHUNK(tc),
+ fmt,
+ ap);
+ if (likely(name_tc)) {
+ tc->name = TC_PTR_FROM_CHUNK(name_tc);
+ _tc_set_name_const(name_tc, ".name");
+ } else {
+ tc->name = NULL;
}
return tc->name;
}
@@ -1376,10 +1444,11 @@ static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va
*/
_PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
const char *name;
va_list ap;
va_start(ap, fmt);
- name = talloc_set_name_v(ptr, fmt, ap);
+ name = tc_set_name_v(tc, fmt, ap);
va_end(ap);
return name;
}
@@ -1395,12 +1464,13 @@ _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, .
va_list ap;
void *ptr;
const char *name;
+ struct talloc_chunk *tc;
- ptr = __talloc(context, size);
+ ptr = __talloc(context, size, &tc);
if (unlikely(ptr == NULL)) return NULL;
va_start(ap, fmt);
- name = talloc_set_name_v(ptr, fmt, ap);
+ name = tc_set_name_v(tc, fmt, ap);
va_end(ap);
if (unlikely(name == NULL)) {
@@ -1490,12 +1560,13 @@ _PUBLIC_ void *talloc_init(const char *fmt, ...)
va_list ap;
void *ptr;
const char *name;
+ struct talloc_chunk *tc;
- ptr = __talloc(NULL, 0);
+ ptr = __talloc(NULL, 0, &tc);
if (unlikely(ptr == NULL)) return NULL;
va_start(ap, fmt);
- name = talloc_set_name_v(ptr, fmt, ap);
+ name = tc_set_name_v(tc, fmt, ap);
va_end(ap);
if (unlikely(name == NULL)) {
@@ -1506,7 +1577,7 @@ _PUBLIC_ void *talloc_init(const char *fmt, ...)
return ptr;
}
-static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
+static inline void _tc_free_children_internal(struct talloc_chunk *tc,
void *ptr,
const char *location)
{
@@ -1522,13 +1593,13 @@ static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
}
- if (unlikely(_talloc_free_internal(child, location) == -1)) {
+ if (unlikely(_tc_free_internal(tc->child, location) == -1)) {
if (talloc_parent_chunk(child) != tc) {
/*
* Destructor already reparented this child.
* No further reparenting needed.
*/
- return;
+ continue;
}
if (new_parent == null_context) {
struct talloc_chunk *p = talloc_parent_chunk(ptr);
@@ -1568,7 +1639,7 @@ _PUBLIC_ void talloc_free_children(void *ptr)
}
}
- _talloc_free_children_internal(tc, ptr, __location__);
+ _tc_free_children_internal(tc, ptr, __location__);
/* .. so we put it back after all other children have been freed */
if (tc_name) {
@@ -1585,7 +1656,8 @@ _PUBLIC_ void talloc_free_children(void *ptr)
*/
_PUBLIC_ void *_talloc(const void *context, size_t size)
{
- return __talloc(context, size);
+ struct talloc_chunk *tc;
+ return __talloc(context, size, &tc);
}
/*
@@ -1593,7 +1665,7 @@ _PUBLIC_ void *_talloc(const void *context, size_t size)
*/
_PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
{
- _talloc_set_name_const(ptr, name);
+ _tc_set_name_const(talloc_chunk_from_ptr(ptr), name);
}
/*
@@ -1742,7 +1814,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
#if ALWAYS_REALLOC
if (pool_hdr) {
- new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE, 0);
+ new_ptr = tc_alloc_pool(tc, size + TC_HDR_SIZE, 0);
pool_hdr->object_count--;
if (new_ptr == NULL) {
@@ -1859,7 +1931,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
}
}
- new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE, 0);
+ new_ptr = tc_alloc_pool(tc, size + TC_HDR_SIZE, 0);
if (new_ptr == NULL) {
new_ptr = malloc(TC_HDR_SIZE+size);
@@ -1870,7 +1942,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
if (new_ptr) {
memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
- _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
+ _tc_free_poolmem(tc, __location__ "_talloc_realloc");
}
}
else {
@@ -1912,7 +1984,7 @@ got_new_ptr:
}
tc->size = size;
- _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
+ _tc_set_name_const(tc, name);
return TC_PTR_FROM_CHUNK(tc);
}
@@ -2295,14 +2367,15 @@ _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const c
static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
{
char *ret;
+ struct talloc_chunk *tc;
- ret = (char *)__talloc(t, len + 1);
+ ret = (char *)__talloc(t, len + 1, &tc);
if (unlikely(!ret)) return NULL;
memcpy(ret, p, len);
ret[len] = 0;
- _talloc_set_name_const(ret, ret);
+ _tc_set_name_const(tc, ret);
return ret;
}
@@ -2336,7 +2409,7 @@ static inline char *__talloc_strlendup_append(char *s, size_t slen,
memcpy(&ret[slen], a, alen);
ret[slen+alen] = 0;
- _talloc_set_name_const(ret, ret);
+ _tc_set_name_const(talloc_chunk_from_ptr(ret), ret);
return ret;
}
@@ -2428,11 +2501,18 @@ _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
#endif
#endif
-_PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
+static struct talloc_chunk *_vasprintf_tc(const void *t,
+ const char *fmt,
+ va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+static struct talloc_chunk *_vasprintf_tc(const void *t,
+ const char *fmt,
+ va_list ap)
{
int len;
char *ret;
va_list ap2;
+ struct talloc_chunk *tc;
char buf[1024];
/* this call looks strange, but it makes it work on older solaris boxes */
@@ -2443,7 +2523,7 @@ _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
return NULL;
}
- ret = (char *)__talloc(t, len+1);
+ ret = (char *)__talloc(t, len+1, &tc);
if (unlikely(!ret)) return NULL;
if (len < sizeof(buf)) {
@@ -2454,8 +2534,17 @@ _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
va_end(ap2);
}
- _talloc_set_name_const(ret, ret);
- return ret;
+ _tc_set_name_const(tc, ret);
+ return tc;
+}
+
+_PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
+{
+ struct talloc_chunk *tc = _vasprintf_tc(t, fmt, ap);
+ if (tc == NULL) {
+ return NULL;
+ }
+ return TC_PTR_FROM_CHUNK(tc);
}
@@ -2506,7 +2595,7 @@ static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
vsnprintf(s + slen, alen + 1, fmt, ap2);
va_end(ap2);
- _talloc_set_name_const(s, s);
+ _tc_set_name_const(talloc_chunk_from_ptr(s), s);
return s;
}
@@ -2772,7 +2861,7 @@ static inline bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t s
/*
Update memory limits when freeing a talloc_chunk.
*/
-static void talloc_memlimit_update_on_free(struct talloc_chunk *tc)
+static void tc_memlimit_update_on_free(struct talloc_chunk *tc)
{
size_t limit_shrink_size;
diff --git a/lib/talloc/test_magic_differs.sh b/lib/talloc/test_magic_differs.sh
index 0f765f0..1b6ba2e 100755
--- a/lib/talloc/test_magic_differs.sh
+++ b/lib/talloc/test_magic_differs.sh
@@ -4,10 +4,12 @@
echo "test: magic differs"
-if [
- "`./talloc_test_magic_differs_helper`" != "`./talloc_test_magic_differs_helper`"
-]; then
- echo "failure: magic remained the same between executions"
+helper=$1
+m1=$($helper)
+m2=$($helper)
+
+if [ $m1 -eq $m2 ]; then
+ echo "failure: magic remained the same between executions ($m1 vs $m2)"
exit 1
fi
diff --git a/lib/talloc/test_pytalloc.c b/lib/talloc/test_pytalloc.c
index f66b4e5..a7c31c1 100644
--- a/lib/talloc/test_pytalloc.c
+++ b/lib/talloc/test_pytalloc.c
@@ -42,24 +42,53 @@ static PyObject *testpytalloc_get_object_type(PyObject *mod) {
return type;
}
+static PyObject *testpytalloc_base_new(PyTypeObject *mod)
+{
+ char *obj = talloc_strdup(NULL, "This is a test string for a BaseObject");;
+ return pytalloc_steal(pytalloc_GetBaseObjectType(), obj);
+}
+
+static PyObject *testpytalloc_base_get_object_type(PyObject *mod) {
+ PyObject *type = (PyObject *)pytalloc_GetBaseObjectType();
+ Py_INCREF(type);
+ return type;
+}
+
static PyObject *testpytalloc_reference(PyObject *mod, PyObject *args) {
- pytalloc_Object *source = NULL;
+ PyObject *source = NULL;
void *ptr;
if (!PyArg_ParseTuple(args, "O!", pytalloc_GetObjectType(), &source))
return NULL;
- ptr = source->ptr;
+ ptr = pytalloc_get_ptr(source);
return pytalloc_reference_ex(pytalloc_GetObjectType(), ptr, ptr);
}
+static PyObject *testpytalloc_base_reference(PyObject *mod, PyObject *args) {
+ PyObject *source = NULL;
+ void *mem_ctx;
+
+ if (!PyArg_ParseTuple(args, "O!", pytalloc_GetBaseObjectType(), &source)) {
+ return NULL;
+ }
+ mem_ctx = pytalloc_get_mem_ctx(source);
+ return pytalloc_reference_ex(pytalloc_GetBaseObjectType(), mem_ctx, mem_ctx);
+}
+
static PyMethodDef test_talloc_methods[] = {
{ "new", (PyCFunction)testpytalloc_new, METH_NOARGS,
"create a talloc Object with a testing string"},
{ "get_object_type", (PyCFunction)testpytalloc_get_object_type, METH_NOARGS,
"call pytalloc_GetObjectType"},
+ { "base_new", (PyCFunction)testpytalloc_base_new, METH_NOARGS,
+ "create a talloc BaseObject with a testing string"},
+ { "base_get_object_type", (PyCFunction)testpytalloc_base_get_object_type, METH_NOARGS,
+ "call pytalloc_GetBaseObjectType"},
{ "reference", (PyCFunction)testpytalloc_reference, METH_VARARGS,
"call pytalloc_reference_ex"},
+ { "base_reference", (PyCFunction)testpytalloc_base_reference, METH_VARARGS,
+ "call pytalloc_reference_ex"},
{ NULL }
};
@@ -104,6 +133,46 @@ static PyTypeObject DObject_Type = {
.tp_doc = "test talloc object that calls a function when underlying data is freed\n",
};
+static PyTypeObject DBaseObject_Type;
+
+static int d_base_object_destructor(void *ptr)
+{
+ PyObject *destructor_func = *talloc_get_type(ptr, PyObject*);
+ PyObject *ret;
+ ret = PyObject_CallObject(destructor_func, NULL);
+ Py_DECREF(destructor_func);
+ if (ret == NULL) {
+ PyErr_Print();
+ } else {
+ Py_DECREF(ret);
+ }
+ return 0;
+}
+
+static PyObject *d_base_object_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *destructor_func = NULL;
+ PyObject **obj;
+
+ if (!PyArg_ParseTuple(args, "O", &destructor_func))
+ return NULL;
+ Py_INCREF(destructor_func);
+
+ obj = talloc(NULL, PyObject*);
+ *obj = destructor_func;
+
+ talloc_set_destructor((void*)obj, d_base_object_destructor);
+ return pytalloc_steal(&DBaseObject_Type, obj);
+}
+
+static PyTypeObject DBaseObject_Type = {
+ .tp_name = "_test_pytalloc.DBaseObject",
+ .tp_methods = NULL,
+ .tp_new = d_base_object_new,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_doc = "test talloc object that calls a function when underlying data is freed\n",
+};
+
#define MODULE_DOC PyDoc_STR("Test utility module for pytalloc")
#if PY_MAJOR_VERSION >= 3
@@ -126,6 +195,12 @@ static PyObject *module_init(void)
return NULL;
}
+ DBaseObject_Type.tp_basicsize = pytalloc_BaseObject_size();
+ DBaseObject_Type.tp_base = pytalloc_GetBaseObjectType();
+ if (PyType_Ready(&DBaseObject_Type) < 0) {
+ return NULL;
+ }
+
#if PY_MAJOR_VERSION >= 3
m = PyModule_Create(&moduledef);
#else
@@ -140,6 +215,10 @@ static PyObject *module_init(void)
Py_INCREF(DObject_Type.tp_base);
PyModule_AddObject(m, "DObject", (PyObject *)&DObject_Type);
+ Py_INCREF(&DBaseObject_Type);
+ Py_INCREF(DBaseObject_Type.tp_base);
+ PyModule_AddObject(m, "DBaseObject", (PyObject *)&DBaseObject_Type);
+
return m;
}
diff --git a/lib/talloc/test_pytalloc.py b/lib/talloc/test_pytalloc.py
index a613373..2e58d28 100644
--- a/lib/talloc/test_pytalloc.py
+++ b/lib/talloc/test_pytalloc.py
@@ -43,6 +43,12 @@ class TallocTests(unittest.TestCase):
self.assertTrue(repr(obj).startswith(prefix))
self.assertEqual(repr(obj), str(obj))
+ def test_base_repr(self):
+ obj = _test_pytalloc.base_new()
+ prefix = '<talloc.BaseObject talloc based object at'
+ self.assertTrue(repr(obj).startswith(prefix))
+ self.assertEqual(repr(obj), str(obj))
+
def test_destructor(self):
# Check correct lifetime of the talloc'd data
lst = []
@@ -52,6 +58,15 @@ class TallocTests(unittest.TestCase):
gc.collect()
self.assertEqual(lst, ['dead'])
+ def test_base_destructor(self):
+ # Check correct lifetime of the talloc'd data
+ lst = []
+ obj = _test_pytalloc.DBaseObject(lambda: lst.append('dead'))
+ self.assertEqual(lst, [])
+ del obj
+ gc.collect()
+ self.assertEqual(lst, ['dead'])
+
class TallocComparisonTests(unittest.TestCase):
@@ -94,13 +109,54 @@ class TallocComparisonTests(unittest.TestCase):
self.assertFalse(obj1 >= obj2)
self.assertFalse(obj1 > obj2)
+class TallocBaseComparisonTests(unittest.TestCase):
+
+ def test_compare_same(self):
+ obj1 = _test_pytalloc.base_new()
+ self.assertTrue(obj1 == obj1)
+ self.assertFalse(obj1 != obj1)
+ self.assertTrue(obj1 <= obj1)
+ self.assertFalse(obj1 < obj1)
+ self.assertTrue(obj1 >= obj1)
+ self.assertFalse(obj1 > obj1)
+
+ def test_compare_different(self):
+ # object comparison is consistent
+ obj1, obj2 = sorted([
+ _test_pytalloc.base_new(),
+ _test_pytalloc.base_new()])
+ self.assertFalse(obj1 == obj2)
+ self.assertTrue(obj1 != obj2)
+ self.assertTrue(obj1 <= obj2)
+ self.assertTrue(obj1 < obj2)
+ self.assertFalse(obj1 >= obj2)
+ self.assertFalse(obj1 > obj2)
+
+ def test_compare_different_types(self):
+ # object comparison falls back to comparing types
+ if sys.version_info >= (3, 0):
+ # In Python 3, types are unorderable -- nothing to test
+ return
+ if talloc.BaseObject < _test_pytalloc.DBaseObject:
+ obj1 = _test_pytalloc.base_new()
+ obj2 = _test_pytalloc.DBaseObject(dummy_func)
+ else:
+ obj2 = _test_pytalloc.base_new()
+ obj1 = _test_pytalloc.DBaseObject(dummy_func)
+ self.assertFalse(obj1 == obj2)
+ self.assertTrue(obj1 != obj2)
+ self.assertTrue(obj1 <= obj2)
+ self.assertTrue(obj1 < obj2)
+ self.assertFalse(obj1 >= obj2)
+ self.assertFalse(obj1 > obj2)
+
class TallocUtilTests(unittest.TestCase):
def test_get_type(self):
self.assertTrue(talloc.Object is _test_pytalloc.get_object_type())
- def test_refrence(self):
+ def test_reference(self):
# Check correct lifetime of the talloc'd data with multiple references
lst = []
obj = _test_pytalloc.DObject(lambda: lst.append('dead'))
@@ -112,6 +168,21 @@ class TallocUtilTests(unittest.TestCase):
gc.collect()
self.assertEqual(lst, ['dead'])
+ def test_get_base_type(self):
+ self.assertTrue(talloc.BaseObject is _test_pytalloc.base_get_object_type())
+
+ def test_base_reference(self):
+ # Check correct lifetime of the talloc'd data with multiple references
+ lst = []
+ obj = _test_pytalloc.DBaseObject(lambda: lst.append('dead'))
+ ref = _test_pytalloc.base_reference(obj)
+ del obj
+ gc.collect()
+ self.assertEqual(lst, [])
+ del ref
+ gc.collect()
+ self.assertEqual(lst, ['dead'])
+
if __name__ == '__main__':
unittest.TestProgram()
diff --git a/lib/talloc/testsuite.c b/lib/talloc/testsuite.c
index 34410b8..835d38b 100644
--- a/lib/talloc/testsuite.c
+++ b/lib/talloc/testsuite.c
@@ -34,18 +34,24 @@
#include <unistd.h>
#include <sys/wait.h>
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <assert.h>
+
#include "talloc_testsuite.h"
-static struct timeval timeval_current(void)
+static struct timeval private_timeval_current(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv;
}
-static double timeval_elapsed(struct timeval *tv)
+static double private_timeval_elapsed(struct timeval *tv)
{
- struct timeval tv2 = timeval_current();
+ struct timeval tv2 = private_timeval_current();
return (tv2.tv_sec - tv->tv_sec) +
(tv2.tv_usec - tv->tv_usec)*1.0e-6;
}
@@ -604,7 +610,7 @@ static bool test_realloc_child(void)
void *root;
struct el2 {
const char *name;
- } *el2;
+ } *el2, *el2_2, *el2_3;
struct el1 {
int count;
struct el2 **list, **list2, **list3;
@@ -628,13 +634,22 @@ static bool test_realloc_child(void)
el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
el2 = talloc(el1->list, struct el2);
- el2 = talloc(el1->list2, struct el2);
- el2 = talloc(el1->list3, struct el2);
- (void)el2;
+ CHECK_PARENT("el2", el2, el1->list);
+ el2_2 = talloc(el1->list2, struct el2);
+ CHECK_PARENT("el2", el2_2, el1->list2);
+ el2_3 = talloc(el1->list3, struct el2);
+ CHECK_PARENT("el2", el2_3, el1->list3);
el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
+ CHECK_PARENT("el1_after_realloc", el1->list, el1);
el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
+ CHECK_PARENT("el1_after_realloc", el1->list2, el1);
el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
+ CHECK_PARENT("el1_after_realloc", el1->list3, el1);
+
+ CHECK_PARENT("el2", el2, el1->list);
+ CHECK_PARENT("el2", el2_2, el1->list2);
+ CHECK_PARENT("el2", el2_3, el1->list3);
talloc_free(root);
@@ -835,7 +850,7 @@ static bool test_speed(void)
printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
- tv = timeval_current();
+ tv = private_timeval_current();
count = 0;
do {
void *p1, *p2, *p3;
@@ -848,15 +863,15 @@ static bool test_speed(void)
talloc_free(p1);
}
count += 3 * loop;
- } while (timeval_elapsed(&tv) < 5.0);
+ } while (private_timeval_elapsed(&tv) < 5.0);
- fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
+ fprintf(stderr, "talloc: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
talloc_free(ctx);
ctx = talloc_pool(NULL, 1024);
- tv = timeval_current();
+ tv = private_timeval_current();
count = 0;
do {
void *p1, *p2, *p3;
@@ -869,13 +884,13 @@ static bool test_speed(void)
talloc_free(p1);
}
count += 3 * loop;
- } while (timeval_elapsed(&tv) < 5.0);
+ } while (private_timeval_elapsed(&tv) < 5.0);
talloc_free(ctx);
- fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
+ fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
- tv = timeval_current();
+ tv = private_timeval_current();
count = 0;
do {
void *p1, *p2, *p3;
@@ -888,8 +903,8 @@ static bool test_speed(void)
free(p3);
}
count += 3 * loop;
- } while (timeval_elapsed(&tv) < 5.0);
- fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
+ } while (private_timeval_elapsed(&tv) < 5.0);
+ fprintf(stderr, "malloc: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
printf("success: speed\n");
@@ -1750,7 +1765,8 @@ static void *thread_fn(void *arg)
ret = pthread_cond_wait(&condvar, &mtx);
if (ret != 0) {
talloc_free(top_ctx);
- pthread_mutex_unlock(&mtx);
+ ret = pthread_mutex_unlock(&mtx);
+ assert(ret == 0);
return NULL;
}
}
@@ -1760,7 +1776,8 @@ static void *thread_fn(void *arg)
/* Tell the main thread it's ready for pickup. */
pthread_cond_broadcast(&condvar);
- pthread_mutex_unlock(&mtx);
+ ret = pthread_mutex_unlock(&mtx);
+ assert(ret == 0);
talloc_free(top_ctx);
return NULL;
@@ -1795,11 +1812,11 @@ static bool test_pthread_talloc_passing(void)
* They will use their own toplevel contexts.
*/
for (i = 0; i < NUM_THREADS; i++) {
- (void)snprintf(str_array[i],
- 20,
- "thread:%d",
- i);
- if (str_array[i] == NULL) {
+ ret = snprintf(str_array[i],
+ 20,
+ "thread:%d",
+ i);
+ if (ret < 0) {
printf("snprintf %d failed\n", i);
return false;
}
@@ -1831,8 +1848,8 @@ static bool test_pthread_talloc_passing(void)
printf("pthread_cond_wait %d failed (%d)\n", i,
ret);
talloc_free(mem_ctx);
- pthread_mutex_unlock(&mtx);
- return false;
+ ret = pthread_mutex_unlock(&mtx);
+ assert(ret == 0);
}
}
@@ -1841,7 +1858,8 @@ static bool test_pthread_talloc_passing(void)
/* Tell the sub-threads we're ready for another. */
pthread_cond_broadcast(&condvar);
- pthread_mutex_unlock(&mtx);
+ ret = pthread_mutex_unlock(&mtx);
+ assert(ret == 0);
}
CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
@@ -1865,6 +1883,11 @@ static void test_magic_protection_abort(const char *reason)
}
}
+static int test_magic_protection_destructor(int *ptr)
+{
+ _exit(404); /* Not 42 */
+}
+
static bool test_magic_protection(void)
{
void *pool = talloc_pool(NULL, 1024);
@@ -1883,6 +1906,7 @@ static bool test_magic_protection(void)
pid = fork();
if (pid == 0) {
talloc_set_abort_fn(test_magic_protection_abort);
+ talloc_set_destructor(p2, test_magic_protection_destructor);
/*
* Simulate a security attack
diff --git a/lib/talloc/wscript b/lib/talloc/wscript
index 1616791..41f3be7 100644
--- a/lib/talloc/wscript
+++ b/lib/talloc/wscript
@@ -1,7 +1,7 @@
#!/usr/bin/env python
APPNAME = 'talloc'
-VERSION = '2.1.5'
+VERSION = '2.1.8'
blddir = 'bin'
@@ -133,7 +133,7 @@ def build(bld):
vnum=VERSION,
hide_symbols=True,
abi_directory='ABI',
- abi_match='pytalloc_*',
+ abi_match='pytalloc_* _pytalloc_*',
private_library=private_library,
public_headers=('' if private_library else 'pytalloc.h'),
pc_files='pytalloc-util.pc'
@@ -158,10 +158,11 @@ def test(ctx):
cmd = os.path.join(Utils.g_module.blddir, 'talloc_testsuite')
ret = samba_utils.RUN_COMMAND(cmd)
print("testsuite returned %d" % ret)
+ magic_helper_cmd = os.path.join(Utils.g_module.blddir, 'talloc_test_magic_differs_helper')
magic_cmd = os.path.join(srcdir, 'lib', 'talloc',
'test_magic_differs.sh')
- magic_ret = samba_utils.RUN_COMMAND(magic_cmd)
+ magic_ret = samba_utils.RUN_COMMAND(magic_cmd + " " + magic_helper_cmd)
print("magic differs test returned %d" % magic_ret)
pyret = samba_utils.RUN_PYTHON_TESTS(['test_pytalloc.py'])
print("python testsuite returned %d" % pyret)
diff --git a/lib/tdb/ABI/tdb-1.3.10.sigs b/lib/tdb/ABI/tdb-1.3.10.sigs
new file mode 100644
index 0000000..2545c99
--- /dev/null
+++ b/lib/tdb/ABI/tdb-1.3.10.sigs
@@ -0,0 +1,69 @@
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_jenkins_hash: unsigned int (TDB_DATA *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: dptr = 0xXXXX, dsize = 0
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_rescue: int (struct tdb_context *, void (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_runtime_check_for_robust_mutexes: bool (void)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+tdb_summary: char *(struct tdb_context *)
+tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_start_nonblock: int (struct tdb_context *)
+tdb_transaction_write_lock_mark: int (struct tdb_context *)
+tdb_transaction_write_lock_unmark: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
diff --git a/lib/tdb/ABI/tdb-1.3.11.sigs b/lib/tdb/ABI/tdb-1.3.11.sigs
new file mode 100644
index 0000000..48f4278
--- /dev/null
+++ b/lib/tdb/ABI/tdb-1.3.11.sigs
@@ -0,0 +1,70 @@
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_jenkins_hash: unsigned int (TDB_DATA *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: dptr = 0xXXXX, dsize = 0
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_rescue: int (struct tdb_context *, void (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_runtime_check_for_robust_mutexes: bool (void)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+tdb_storev: int (struct tdb_context *, TDB_DATA, const TDB_DATA *, int, int)
+tdb_summary: char *(struct tdb_context *)
+tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_start_nonblock: int (struct tdb_context *)
+tdb_transaction_write_lock_mark: int (struct tdb_context *)
+tdb_transaction_write_lock_unmark: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
diff --git a/lib/tdb/ABI/tdb-1.3.12.sigs b/lib/tdb/ABI/tdb-1.3.12.sigs
new file mode 100644
index 0000000..48f4278
--- /dev/null
+++ b/lib/tdb/ABI/tdb-1.3.12.sigs
@@ -0,0 +1,70 @@
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_jenkins_hash: unsigned int (TDB_DATA *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: dptr = 0xXXXX, dsize = 0
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_rescue: int (struct tdb_context *, void (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_runtime_check_for_robust_mutexes: bool (void)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+tdb_storev: int (struct tdb_context *, TDB_DATA, const TDB_DATA *, int, int)
+tdb_summary: char *(struct tdb_context *)
+tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_start_nonblock: int (struct tdb_context *)
+tdb_transaction_write_lock_mark: int (struct tdb_context *)
+tdb_transaction_write_lock_unmark: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
diff --git a/lib/tdb/ABI/tdb-1.3.9.sigs b/lib/tdb/ABI/tdb-1.3.9.sigs
new file mode 100644
index 0000000..2545c99
--- /dev/null
+++ b/lib/tdb/ABI/tdb-1.3.9.sigs
@@ -0,0 +1,69 @@
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_jenkins_hash: unsigned int (TDB_DATA *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: dptr = 0xXXXX, dsize = 0
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_rescue: int (struct tdb_context *, void (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_runtime_check_for_robust_mutexes: bool (void)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+tdb_summary: char *(struct tdb_context *)
+tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_start_nonblock: int (struct tdb_context *)
+tdb_transaction_write_lock_mark: int (struct tdb_context *)
+tdb_transaction_write_lock_unmark: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
diff --git a/lib/tdb/common/mutex.c b/lib/tdb/common/mutex.c
index fae43d4..cac3916 100644
--- a/lib/tdb/common/mutex.c
+++ b/lib/tdb/common/mutex.c
@@ -603,12 +603,13 @@ int tdb_mutex_init(struct tdb_context *tdb)
fail:
pthread_mutexattr_destroy(&ma);
fail_munmap:
- tdb_mutex_munmap(tdb);
if (ret == 0) {
return 0;
}
+ tdb_mutex_munmap(tdb);
+
errno = ret;
return -1;
}
@@ -623,6 +624,10 @@ int tdb_mutex_mmap(struct tdb_context *tdb)
return 0;
}
+ if (tdb->mutexes != NULL) {
+ return 0;
+ }
+
ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE,
tdb->fd, 0);
if (ptr == MAP_FAILED) {
@@ -636,13 +641,20 @@ int tdb_mutex_mmap(struct tdb_context *tdb)
int tdb_mutex_munmap(struct tdb_context *tdb)
{
size_t len;
+ int ret;
len = tdb_mutex_size(tdb);
if (len == 0) {
return 0;
}
- return munmap(tdb->mutexes, len);
+ ret = munmap(tdb->mutexes, len);
+ if (ret == -1) {
+ return -1;
+ }
+ tdb->mutexes = NULL;
+
+ return 0;
}
static bool tdb_mutex_locking_cached;
@@ -766,8 +778,8 @@ static void tdb_robust_mutex_handler(int sig)
_PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
{
- void *ptr;
- pthread_mutex_t *m;
+ void *ptr = NULL;
+ pthread_mutex_t *m = NULL;
pthread_mutexattr_t ma;
int ret = 1;
int pipe_down[2] = { -1, -1 };
@@ -775,8 +787,10 @@ _PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
ssize_t nread;
char c = 0;
bool ok;
- int status;
static bool initialized;
+ sigset_t mask, old_mask, suspend_mask;
+ bool cleanup_ma = false;
+ bool cleanup_sigmask = false;
if (initialized) {
return tdb_mutex_locking_cached;
@@ -784,6 +798,8 @@ _PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
initialized = true;
+ sigemptyset(&suspend_mask);
+
ok = tdb_mutex_locking_supported();
if (!ok) {
return false;
@@ -796,41 +812,56 @@ _PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
if (ptr == MAP_FAILED) {
return false;
}
- m = (pthread_mutex_t *)ptr;
ret = pipe(pipe_down);
if (ret != 0) {
- goto cleanup_mmap;
+ goto cleanup;
}
ret = pipe(pipe_up);
if (ret != 0) {
- goto cleanup_pipe;
+ goto cleanup;
}
ret = pthread_mutexattr_init(&ma);
if (ret != 0) {
- goto cleanup_pipe;
+ goto cleanup;
}
+ cleanup_ma = true;
ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
if (ret != 0) {
- goto cleanup_ma;
+ goto cleanup;
}
ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
if (ret != 0) {
- goto cleanup_ma;
+ goto cleanup;
}
ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
if (ret != 0) {
- goto cleanup_ma;
+ goto cleanup;
}
- ret = pthread_mutex_init(m, &ma);
+ ret = pthread_mutex_init(ptr, &ma);
if (ret != 0) {
- goto cleanup_ma;
+ goto cleanup;
}
+ m = (pthread_mutex_t *)ptr;
+
+ /*
+ * Block SIGCHLD so we can atomically wait for it later with
+ * sigsuspend()
+ */
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ ret = pthread_sigmask(SIG_BLOCK, &mask, &old_mask);
+ if (ret != 0) {
+ goto cleanup;
+ }
+ cleanup_sigmask = true;
+ suspend_mask = old_mask;
+ sigdelset(&suspend_mask, SIGCHLD);
if (tdb_robust_mutex_setup_sigchild(tdb_robust_mutex_handler,
&tdb_robust_mutext_old_handler) == false) {
- goto cleanup_ma;
+ goto cleanup;
}
tdb_robust_mutex_pid = fork();
@@ -854,7 +885,7 @@ _PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
_exit(0);
}
if (tdb_robust_mutex_pid == -1) {
- goto cleanup_sig_child;
+ goto cleanup;
}
close(pipe_down[0]);
pipe_down[0] = -1;
@@ -863,7 +894,7 @@ _PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
nread = read(pipe_up[0], &ret, sizeof(ret));
if (nread != sizeof(ret)) {
- goto cleanup_child;
+ goto cleanup;
}
ret = pthread_mutex_trylock(m);
@@ -871,83 +902,77 @@ _PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
if (ret == 0) {
pthread_mutex_unlock(m);
}
- goto cleanup_child;
+ goto cleanup;
}
if (write(pipe_down[1], &c, 1) != 1) {
- goto cleanup_child;
+ goto cleanup;
}
nread = read(pipe_up[0], &c, 1);
if (nread != 0) {
- goto cleanup_child;
+ goto cleanup;
}
while (tdb_robust_mutex_pid > 0) {
- pid_t pid;
-
- errno = 0;
- pid = waitpid(tdb_robust_mutex_pid, &status, 0);
- if (pid == tdb_robust_mutex_pid) {
- tdb_robust_mutex_pid = -1;
- break;
- }
- if (pid == -1 && errno != EINTR) {
- goto cleanup_child;
+ ret = sigsuspend(&suspend_mask);
+ if (ret != -1 || errno != EINTR) {
+ abort();
}
}
tdb_robust_mutex_setup_sigchild(tdb_robust_mutext_old_handler, NULL);
+ tdb_robust_mutext_old_handler = SIG_ERR;
ret = pthread_mutex_trylock(m);
if (ret != EOWNERDEAD) {
if (ret == 0) {
pthread_mutex_unlock(m);
}
- goto cleanup_m;
+ goto cleanup;
}
ret = pthread_mutex_consistent(m);
if (ret != 0) {
- goto cleanup_m;
+ goto cleanup;
}
ret = pthread_mutex_trylock(m);
- if (ret != EDEADLK) {
+ if (ret != EDEADLK && ret != EBUSY) {
pthread_mutex_unlock(m);
- goto cleanup_m;
+ goto cleanup;
}
ret = pthread_mutex_unlock(m);
if (ret != 0) {
- goto cleanup_m;
+ goto cleanup;
}
tdb_mutex_locking_cached = true;
- goto cleanup_m;
-cleanup_child:
+cleanup:
while (tdb_robust_mutex_pid > 0) {
- pid_t pid;
-
kill(tdb_robust_mutex_pid, SIGKILL);
-
- errno = 0;
- pid = waitpid(tdb_robust_mutex_pid, &status, 0);
- if (pid == tdb_robust_mutex_pid) {
- tdb_robust_mutex_pid = -1;
- break;
+ ret = sigsuspend(&suspend_mask);
+ if (ret != -1 || errno != EINTR) {
+ abort();
}
- if (pid == -1 && errno != EINTR) {
- break;
+ }
+
+ if (tdb_robust_mutext_old_handler != SIG_ERR) {
+ tdb_robust_mutex_setup_sigchild(tdb_robust_mutext_old_handler, NULL);
+ }
+ if (cleanup_sigmask) {
+ ret = pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
+ if (ret != 0) {
+ abort();
}
}
-cleanup_sig_child:
- tdb_robust_mutex_setup_sigchild(tdb_robust_mutext_old_handler, NULL);
-cleanup_m:
- pthread_mutex_destroy(m);
-cleanup_ma:
- pthread_mutexattr_destroy(&ma);
-cleanup_pipe:
+ if (m != NULL) {
+ pthread_mutex_destroy(m);
+ }
+ if (cleanup_ma) {
+ pthread_mutexattr_destroy(&ma);
+ }
if (pipe_down[0] != -1) {
close(pipe_down[0]);
}
@@ -960,8 +985,9 @@ cleanup_pipe:
if (pipe_up[1] != -1) {
close(pipe_up[1]);
}
-cleanup_mmap:
- munmap(ptr, sizeof(pthread_mutex_t));
+ if (ptr != NULL) {
+ munmap(ptr, sizeof(pthread_mutex_t));
+ }
return tdb_mutex_locking_cached;
}
diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index 9885d8c..a67d8fb 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -59,6 +59,11 @@ static void tdb_increment_seqnum(struct tdb_context *tdb)
return;
}
+ if (tdb->transaction != NULL) {
+ tdb_increment_seqnum_nonblock(tdb);
+ return;
+ }
+
if (tdb_nest_lock(tdb, TDB_SEQNUM_OFS, F_WRLCK,
TDB_LOCK_WAIT|TDB_LOCK_PROBE) != 0) {
return;
@@ -124,16 +129,32 @@ tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t has
static TDB_DATA _tdb_fetch(struct tdb_context *tdb, TDB_DATA key);
+struct tdb_update_hash_state {
+ const TDB_DATA *dbufs;
+ int num_dbufs;
+ tdb_len_t dbufs_len;
+};
+
static int tdb_update_hash_cmp(TDB_DATA key, TDB_DATA data, void *private_data)
{
- TDB_DATA *dbuf = (TDB_DATA *)private_data;
+ struct tdb_update_hash_state *state = private_data;
+ unsigned char *dptr = data.dptr;
+ int i;
- if (dbuf->dsize != data.dsize) {
+ if (state->dbufs_len != data.dsize) {
return -1;
}
- if (memcmp(dbuf->dptr, data.dptr, data.dsize) != 0) {
- return -1;
+
+ for (i=0; i<state->num_dbufs; i++) {
+ TDB_DATA dbuf = state->dbufs[i];
+ int ret;
+ ret = memcmp(dptr, dbuf.dptr, dbuf.dsize);
+ if (ret != 0) {
+ return -1;
+ }
+ dptr += dbuf.dsize;
}
+
return 0;
}
@@ -141,10 +162,14 @@ static int tdb_update_hash_cmp(TDB_DATA key, TDB_DATA data, void *private_data)
is <= the old data size and the key exists.
on failure return -1.
*/
-static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, TDB_DATA dbuf)
+static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key,
+ uint32_t hash,
+ const TDB_DATA *dbufs, int num_dbufs,
+ tdb_len_t dbufs_len)
{
struct tdb_record rec;
- tdb_off_t rec_ptr;
+ tdb_off_t rec_ptr, ofs;
+ int i;
/* find entry */
if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
@@ -152,26 +177,41 @@ static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
/* it could be an exact duplicate of what is there - this is
* surprisingly common (eg. with a ldb re-index). */
- if (rec.key_len == key.dsize &&
- rec.data_len == dbuf.dsize &&
- rec.full_hash == hash &&
- tdb_parse_record(tdb, key, tdb_update_hash_cmp, &dbuf) == 0) {
- return 0;
+ if (rec.data_len == dbufs_len) {
+ struct tdb_update_hash_state state = {
+ .dbufs = dbufs, .num_dbufs = num_dbufs,
+ .dbufs_len = dbufs_len
+ };
+ int ret;
+
+ ret = tdb_parse_record(tdb, key, tdb_update_hash_cmp, &state);
+ if (ret == 0) {
+ return 0;
+ }
}
/* must be long enough key, data and tailer */
- if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) {
+ if (rec.rec_len < key.dsize + dbufs_len + sizeof(tdb_off_t)) {
tdb->ecode = TDB_SUCCESS; /* Not really an error */
return -1;
}
- if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
- dbuf.dptr, dbuf.dsize) == -1)
- return -1;
+ ofs = rec_ptr + sizeof(rec) + rec.key_len;
+
+ for (i=0; i<num_dbufs; i++) {
+ TDB_DATA dbuf = dbufs[i];
+ int ret;
- if (dbuf.dsize != rec.data_len) {
+ ret = tdb->methods->tdb_write(tdb, ofs, dbuf.dptr, dbuf.dsize);
+ if (ret == -1) {
+ return -1;
+ }
+ ofs += dbuf.dsize;
+ }
+
+ if (dbufs_len != rec.data_len) {
/* update size */
- rec.data_len = dbuf.dsize;
+ rec.data_len = dbufs_len;
return tdb_rec_write(tdb, rec_ptr, &rec);
}
@@ -486,13 +526,34 @@ tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
return best_rec_ptr;
}
-static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
- TDB_DATA dbuf, int flag, uint32_t hash)
+static int _tdb_storev(struct tdb_context *tdb, TDB_DATA key,
+ const TDB_DATA *dbufs, int num_dbufs,
+ int flag, uint32_t hash)
{
struct tdb_record rec;
- tdb_off_t rec_ptr;
+ tdb_off_t rec_ptr, ofs;
+ tdb_len_t rec_len, dbufs_len;
+ int i;
int ret = -1;
+ dbufs_len = 0;
+
+ for (i=0; i<num_dbufs; i++) {
+ size_t dsize = dbufs[i].dsize;
+
+ dbufs_len += dsize;
+ if (dbufs_len < dsize) {
+ tdb->ecode = TDB_ERR_OOM;
+ goto fail;
+ }
+ }
+
+ rec_len = key.dsize + dbufs_len;
+ if ((rec_len < key.dsize) || (rec_len < dbufs_len)) {
+ tdb->ecode = TDB_ERR_OOM;
+ goto fail;
+ }
+
/* check for it existing, on insert. */
if (flag == TDB_INSERT) {
if (tdb_exists_hash(tdb, key, hash)) {
@@ -501,7 +562,8 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
}
} else {
/* first try in-place update, on modify or replace. */
- if (tdb_update_hash(tdb, key, hash, dbuf) == 0) {
+ if (tdb_update_hash(tdb, key, hash, dbufs, num_dbufs,
+ dbufs_len) == 0) {
goto done;
}
if (tdb->ecode == TDB_ERR_NOEXIST &&
@@ -521,7 +583,7 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
tdb_delete_hash(tdb, key, hash);
/* we have to allocate some space */
- rec_ptr = tdb_allocate(tdb, hash, key.dsize + dbuf.dsize, &rec);
+ rec_ptr = tdb_allocate(tdb, hash, rec_len, &rec);
if (rec_ptr == 0) {
goto fail;
@@ -532,17 +594,36 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
goto fail;
rec.key_len = key.dsize;
- rec.data_len = dbuf.dsize;
+ rec.data_len = dbufs_len;
rec.full_hash = hash;
rec.magic = TDB_MAGIC;
+ ofs = rec_ptr;
+
/* write out and point the top of the hash chain at it */
- if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
- || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec),
- key.dptr, key.dsize) == -1
- || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec)+key.dsize,
- dbuf.dptr, dbuf.dsize) == -1
- || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
+ ret = tdb_rec_write(tdb, ofs, &rec);
+ if (ret == -1) {
+ goto fail;
+ }
+ ofs += sizeof(rec);
+
+ ret = tdb->methods->tdb_write(tdb, ofs, key.dptr, key.dsize);
+ if (ret == -1) {
+ goto fail;
+ }
+ ofs += key.dsize;
+
+ for (i=0; i<num_dbufs; i++) {
+ ret = tdb->methods->tdb_write(tdb, ofs, dbufs[i].dptr,
+ dbufs[i].dsize);
+ if (ret == -1) {
+ goto fail;
+ }
+ ofs += dbufs[i].dsize;
+ }
+
+ ret = tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr);
+ if (ret == -1) {
/* Need to tdb_unallocate() here */
goto fail;
}
@@ -556,6 +637,12 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
return ret;
}
+static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
+ TDB_DATA dbuf, int flag, uint32_t hash)
+{
+ return _tdb_storev(tdb, key, &dbuf, 1, flag, hash);
+}
+
/* store an element in the database, replacing any existing element
with the same key
@@ -583,50 +670,51 @@ _PUBLIC_ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int
return ret;
}
-/* Append to an entry. Create if not exist. */
-_PUBLIC_ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
+_PUBLIC_ int tdb_storev(struct tdb_context *tdb, TDB_DATA key,
+ const TDB_DATA *dbufs, int num_dbufs, int flag)
{
uint32_t hash;
- TDB_DATA dbuf;
- int ret = -1;
+ int ret;
+
+ if (tdb->read_only || tdb->traverse_read) {
+ tdb->ecode = TDB_ERR_RDONLY;
+ tdb_trace_1plusn_rec_flag_ret(tdb, "tdb_storev", key,
+ dbufs, num_dbufs, flag, -1);
+ return -1;
+ }
/* find which hash bucket it is in */
hash = tdb->hash_fn(&key);
if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
return -1;
- dbuf = _tdb_fetch(tdb, key);
+ ret = _tdb_storev(tdb, key, dbufs, num_dbufs, flag, hash);
+ tdb_trace_1plusn_rec_flag_ret(tdb, "tdb_storev", key,
+ dbufs, num_dbufs, flag, -1);
+ tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
+ return ret;
+}
- if (dbuf.dptr == NULL) {
- dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize);
- } else {
- unsigned int new_len = dbuf.dsize + new_dbuf.dsize;
- unsigned char *new_dptr;
-
- /* realloc '0' is special: don't do that. */
- if (new_len == 0)
- new_len = 1;
- new_dptr = (unsigned char *)realloc(dbuf.dptr, new_len);
- if (new_dptr == NULL) {
- free(dbuf.dptr);
- }
- dbuf.dptr = new_dptr;
- }
+/* Append to an entry. Create if not exist. */
+_PUBLIC_ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
+{
+ uint32_t hash;
+ TDB_DATA dbufs[2];
+ int ret = -1;
- if (dbuf.dptr == NULL) {
- tdb->ecode = TDB_ERR_OOM;
- goto failed;
- }
+ /* find which hash bucket it is in */
+ hash = tdb->hash_fn(&key);
+ if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
+ return -1;
- memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize);
- dbuf.dsize += new_dbuf.dsize;
+ dbufs[0] = _tdb_fetch(tdb, key);
+ dbufs[1] = new_dbuf;
- ret = _tdb_store(tdb, key, dbuf, 0, hash);
- tdb_trace_2rec_retrec(tdb, "tdb_append", key, new_dbuf, dbuf);
+ ret = _tdb_storev(tdb, key, dbufs, 2, 0, hash);
+ tdb_trace_2rec_retrec(tdb, "tdb_append", key, dbufs[0], dbufs[1]);
-failed:
tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
- SAFE_FREE(dbuf.dptr);
+ SAFE_FREE(dbufs[0].dptr);
return ret;
}
@@ -785,7 +873,7 @@ static int tdb_free_region(struct tdb_context *tdb, tdb_off_t offset, ssize_t le
*/
_PUBLIC_ int tdb_wipe_all(struct tdb_context *tdb)
{
- int i;
+ uint32_t i;
tdb_off_t offset = 0;
ssize_t data_len;
tdb_off_t recovery_head;
@@ -1127,6 +1215,25 @@ void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op,
tdb_trace_end_ret(tdb, ret);
}
+void tdb_trace_1plusn_rec_flag_ret(struct tdb_context *tdb, const char *op,
+ TDB_DATA rec,
+ const TDB_DATA *recs, int num_recs,
+ unsigned flag, int ret)
+{
+ char msg[1 + sizeof(ret) * 4];
+ int i;
+
+ snprintf(msg, sizeof(msg), " %#x", flag);
+ tdb_trace_start(tdb);
+ tdb_trace_write(tdb, op);
+ tdb_trace_record(tdb, rec);
+ for (i=0; i<num_recs; i++) {
+ tdb_trace_record(tdb, recs[i]);
+ }
+ tdb_trace_write(tdb, msg);
+ tdb_trace_end_ret(tdb, ret);
+}
+
void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret)
{
diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h
index de8d9e6..7ff29aa 100644
--- a/lib/tdb/common/tdb_private.h
+++ b/lib/tdb/common/tdb_private.h
@@ -96,6 +96,10 @@ void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op,
void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op,
TDB_DATA rec1, TDB_DATA rec2, unsigned flag,
int ret);
+void tdb_trace_1plusn_rec_flag_ret(struct tdb_context *tdb, const char *op,
+ TDB_DATA rec,
+ const TDB_DATA *recs, int num_recs,
+ unsigned flag, int ret);
void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret);
#else
@@ -108,6 +112,7 @@ void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
#define tdb_trace_1rec_ret(tdb, op, rec, ret)
#define tdb_trace_1rec_retrec(tdb, op, rec, ret)
#define tdb_trace_2rec_flag_ret(tdb, op, rec1, rec2, flag, ret)
+#define tdb_trace_1plusn_rec_flag_ret(tdb, op, rec, recs, num_recs, flag, ret);
#define tdb_trace_2rec_retrec(tdb, op, rec1, rec2, ret)
#endif /* !TDB_TRACE */
diff --git a/lib/tdb/common/traverse.c b/lib/tdb/common/traverse.c
index e18e3c3..f33ef34 100644
--- a/lib/tdb/common/traverse.c
+++ b/lib/tdb/common/traverse.c
@@ -148,6 +148,13 @@ static int tdb_traverse_internal(struct tdb_context *tdb,
struct tdb_record rec;
int ret = 0, count = 0;
tdb_off_t off;
+ size_t recbuf_len;
+
+ recbuf_len = 4096;
+ key.dptr = malloc(recbuf_len);
+ if (key.dptr == NULL) {
+ return -1;
+ }
/* This was in the initialization, above, but the IRIX compiler
* did not like it. crh
@@ -159,15 +166,44 @@ static int tdb_traverse_internal(struct tdb_context *tdb,
/* tdb_next_lock places locks on the record returned, and its chain */
while ((off = tdb_next_lock(tdb, tl, &rec)) != 0) {
+ tdb_len_t full_len = rec.key_len + rec.data_len;
+ int nread;
+
+ if (full_len > recbuf_len) {
+ recbuf_len = full_len;
+
+ /*
+ * No realloc, we don't need the old data and thus can
+ * do without the memcpy
+ */
+ free(key.dptr);
+ key.dptr = malloc(recbuf_len);
+
+ if (key.dptr == NULL) {
+ ret = -1;
+ if (tdb_unlock(tdb, tl->hash, tl->lock_rw)
+ != 0) {
+ goto out;
+ }
+ if (tdb_unlock_record(tdb, tl->off) != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL,
+ "tdb_traverse: malloc "
+ "failed and unlock_record "
+ "failed!\n"));
+ }
+ goto out;
+ }
+ }
+
if (off == TDB_NEXT_LOCK_ERR) {
ret = -1;
goto out;
}
count++;
/* now read the full record */
- key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec),
- rec.key_len + rec.data_len);
- if (!key.dptr) {
+ nread = tdb->methods->tdb_read(tdb, tl->off + sizeof(rec),
+ key.dptr, full_len, 0);
+ if (nread == -1) {
ret = -1;
if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0)
goto out;
@@ -184,7 +220,6 @@ static int tdb_traverse_internal(struct tdb_context *tdb,
/* Drop chain lock, call out */
if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) {
ret = -1;
- SAFE_FREE(key.dptr);
goto out;
}
if (fn && fn(tdb, key, dbuf, private_data)) {
@@ -194,13 +229,12 @@ static int tdb_traverse_internal(struct tdb_context *tdb,
TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));;
ret = -1;
}
- SAFE_FREE(key.dptr);
goto out;
}
- SAFE_FREE(key.dptr);
}
tdb_trace(tdb, "tdb_traverse_end");
out:
+ SAFE_FREE(key.dptr);
tdb->travlocks.next = tl->next;
if (ret < 0)
return -1;
diff --git a/lib/tdb/include/tdb.h b/lib/tdb/include/tdb.h
index 8478ca2..e86d267 100644
--- a/lib/tdb/include/tdb.h
+++ b/lib/tdb/include/tdb.h
@@ -357,6 +357,32 @@ int tdb_delete(struct tdb_context *tdb, TDB_DATA key);
*/
int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
+
+/**
+ * @brief Store an element in the database.
+ *
+ * This replaces any existing element with the same key.
+ *
+ * @param[in] tdb The tdb to store the entry.
+ *
+ * @param[in] key The key to use to store the entry.
+ *
+ * @param[in] dbufs A vector of memory chunks to write
+ *
+ * @param[in] num_dbufs Length of the dbufs vector
+ *
+ * @param[in] flag The flags to store the key:\n\n
+ * TDB_INSERT: Don't overwrite an existing entry.\n
+ * TDB_MODIFY: Don't create a new entry\n
+ *
+ * @return 0 on success, -1 on error with error code set.
+ *
+ * @see tdb_error()
+ * @see tdb_errorstr()
+ */
+int tdb_storev(struct tdb_context *tdb, TDB_DATA key,
+ const TDB_DATA *dbufs, int num_dbufs, int flag);
+
/**
* @brief Append data to an entry.
*
diff --git a/lib/tdb/test/external-agent.c b/lib/tdb/test/external-agent.c
index 443d382..3c59c06 100644
--- a/lib/tdb/test/external-agent.c
+++ b/lib/tdb/test/external-agent.c
@@ -184,7 +184,8 @@ enum agent_return external_agent_operation(struct agent *agent,
string = malloc(len);
string[0] = op;
- strcpy(string+1, name);
+ strncpy(string+1, name, len - 1);
+ string[len-1] = '\0';
if (write(agent->cmdfd, string, len) != len
|| read(agent->responsefd, &res, sizeof(res)) != sizeof(res))
diff --git a/lib/tdb/tools/tdbdump.c b/lib/tdb/tools/tdbdump.c
index 9a0a7fe..8cf3146 100644
--- a/lib/tdb/tools/tdbdump.c
+++ b/lib/tdb/tools/tdbdump.c
@@ -52,6 +52,9 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *stat
}
static void log_stderr(struct tdb_context *tdb, enum tdb_debug_level level,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+
+static void log_stderr(struct tdb_context *tdb, enum tdb_debug_level level,
const char *fmt, ...)
{
va_list ap;
diff --git a/lib/tdb/tools/tdbtorture.c b/lib/tdb/tools/tdbtorture.c
index e4b8f69..3640dc7 100644
--- a/lib/tdb/tools/tdbtorture.c
+++ b/lib/tdb/tools/tdbtorture.c
@@ -223,8 +223,12 @@ static void usage(void)
static void send_count_and_suicide(int sig)
{
+ ssize_t ret;
+
/* This ensures our successor can continue where we left off. */
- write(count_pipe, &loopnum, sizeof(loopnum));
+ do {
+ ret = write(count_pipe, &loopnum, sizeof(loopnum));
+ } while (ret == -1 && errno == EINTR);
/* This gives a unique signature. */
kill(getpid(), SIGUSR2);
}
@@ -427,8 +431,12 @@ int main(int argc, char * const *argv)
|| WTERMSIG(status) == SIGUSR1) {
/* SIGUSR2 means they wrote to pipe. */
if (WTERMSIG(status) == SIGUSR2) {
- read(pfds[0], &done[j],
- sizeof(done[j]));
+ ssize_t ret;
+
+ do {
+ ret = read(pfds[0], &done[j],
+ sizeof(done[j]));
+ } while (ret == -1 && errno == EINTR);
}
pids[j] = fork();
if (pids[j] == 0)
diff --git a/lib/tdb/wscript b/lib/tdb/wscript
index e5c0ead..34058e4 100644
--- a/lib/tdb/wscript
+++ b/lib/tdb/wscript
@@ -1,7 +1,7 @@
#!/usr/bin/env python
APPNAME = 'tdb'
-VERSION = '1.3.8'
+VERSION = '1.3.12'
blddir = 'bin'
diff --git a/lib/tevent/ABI/tevent-0.9.28.sigs b/lib/tevent/ABI/tevent-0.9.28.sigs
new file mode 100644
index 0000000..1357751
--- /dev/null
+++ b/lib/tevent/ABI/tevent-0.9.28.sigs
@@ -0,0 +1,90 @@
+_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
+_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
+_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
+_tevent_loop_once: int (struct tevent_context *, const char *)
+_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
+_tevent_loop_wait: int (struct tevent_context *, const char *)
+_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
+_tevent_req_callback_data: void *(struct tevent_req *)
+_tevent_req_cancel: bool (struct tevent_req *, const char *)
+_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
+_tevent_req_data: void *(struct tevent_req *)
+_tevent_req_done: void (struct tevent_req *, const char *)
+_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
+_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
+_tevent_req_notify_callback: void (struct tevent_req *, const char *)
+_tevent_req_oom: void (struct tevent_req *, const char *)
+_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_backend_list: const char **(TALLOC_CTX *)
+tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
+tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
+tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
+tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_check_signal: int (struct tevent_context *)
+tevent_common_context_destructor: int (struct tevent_context *)
+tevent_common_fd_destructor: int (struct tevent_fd *)
+tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
+tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
+tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
+tevent_common_loop_immediate: bool (struct tevent_context *)
+tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
+tevent_common_loop_wait: int (struct tevent_context *, const char *)
+tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_context_init: struct tevent_context *(TALLOC_CTX *)
+tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
+tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *)
+tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
+tevent_fd_get_flags: uint16_t (struct tevent_fd *)
+tevent_fd_set_auto_close: void (struct tevent_fd *)
+tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
+tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
+tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *)
+tevent_loop_allow_nesting: void (struct tevent_context *)
+tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
+tevent_num_signals: size_t (void)
+tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_length: size_t (struct tevent_queue *)
+tevent_queue_running: bool (struct tevent_queue *)
+tevent_queue_start: void (struct tevent_queue *)
+tevent_queue_stop: void (struct tevent_queue *)
+tevent_queue_wait_recv: bool (struct tevent_req *)
+tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct tevent_queue *)
+tevent_re_initialise: int (struct tevent_context *)
+tevent_register_backend: bool (const char *, const struct tevent_ops *)
+tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
+tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *)
+tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
+tevent_req_is_in_progress: bool (struct tevent_req *)
+tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
+tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
+tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
+tevent_req_received: void (struct tevent_req *)
+tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
+tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
+tevent_req_set_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_fn)
+tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
+tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
+tevent_sa_info_queue_count: size_t (void)
+tevent_set_abort_fn: void (void (*)(const char *))
+tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
+tevent_set_debug_stderr: int (struct tevent_context *)
+tevent_set_default_backend: void (const char *)
+tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *)
+tevent_signal_support: bool (struct tevent_context *)
+tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *)
+tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *)
+tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
+tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
+tevent_timeval_current: struct timeval (void)
+tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
+tevent_timeval_is_zero: bool (const struct timeval *)
+tevent_timeval_set: struct timeval (uint32_t, uint32_t)
+tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
+tevent_timeval_zero: struct timeval (void)
+tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point)
+tevent_wakeup_recv: bool (struct tevent_req *)
+tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)
diff --git a/lib/tevent/ABI/tevent-0.9.29.sigs b/lib/tevent/ABI/tevent-0.9.29.sigs
new file mode 100644
index 0000000..1357751
--- /dev/null
+++ b/lib/tevent/ABI/tevent-0.9.29.sigs
@@ -0,0 +1,90 @@
+_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
+_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
+_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
+_tevent_loop_once: int (struct tevent_context *, const char *)
+_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
+_tevent_loop_wait: int (struct tevent_context *, const char *)
+_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
+_tevent_req_callback_data: void *(struct tevent_req *)
+_tevent_req_cancel: bool (struct tevent_req *, const char *)
+_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
+_tevent_req_data: void *(struct tevent_req *)
+_tevent_req_done: void (struct tevent_req *, const char *)
+_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
+_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
+_tevent_req_notify_callback: void (struct tevent_req *, const char *)
+_tevent_req_oom: void (struct tevent_req *, const char *)
+_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_backend_list: const char **(TALLOC_CTX *)
+tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
+tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
+tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
+tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_check_signal: int (struct tevent_context *)
+tevent_common_context_destructor: int (struct tevent_context *)
+tevent_common_fd_destructor: int (struct tevent_fd *)
+tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
+tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
+tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
+tevent_common_loop_immediate: bool (struct tevent_context *)
+tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
+tevent_common_loop_wait: int (struct tevent_context *, const char *)
+tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_context_init: struct tevent_context *(TALLOC_CTX *)
+tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
+tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *)
+tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
+tevent_fd_get_flags: uint16_t (struct tevent_fd *)
+tevent_fd_set_auto_close: void (struct tevent_fd *)
+tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
+tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
+tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *)
+tevent_loop_allow_nesting: void (struct tevent_context *)
+tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
+tevent_num_signals: size_t (void)
+tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_length: size_t (struct tevent_queue *)
+tevent_queue_running: bool (struct tevent_queue *)
+tevent_queue_start: void (struct tevent_queue *)
+tevent_queue_stop: void (struct tevent_queue *)
+tevent_queue_wait_recv: bool (struct tevent_req *)
+tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct tevent_queue *)
+tevent_re_initialise: int (struct tevent_context *)
+tevent_register_backend: bool (const char *, const struct tevent_ops *)
+tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
+tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *)
+tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
+tevent_req_is_in_progress: bool (struct tevent_req *)
+tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
+tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
+tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
+tevent_req_received: void (struct tevent_req *)
+tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
+tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
+tevent_req_set_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_fn)
+tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
+tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
+tevent_sa_info_queue_count: size_t (void)
+tevent_set_abort_fn: void (void (*)(const char *))
+tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
+tevent_set_debug_stderr: int (struct tevent_context *)
+tevent_set_default_backend: void (const char *)
+tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *)
+tevent_signal_support: bool (struct tevent_context *)
+tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *)
+tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *)
+tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
+tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
+tevent_timeval_current: struct timeval (void)
+tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
+tevent_timeval_is_zero: bool (const struct timeval *)
+tevent_timeval_set: struct timeval (uint32_t, uint32_t)
+tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
+tevent_timeval_zero: struct timeval (void)
+tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point)
+tevent_wakeup_recv: bool (struct tevent_req *)
+tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)
diff --git a/lib/tevent/ABI/tevent-0.9.30.sigs b/lib/tevent/ABI/tevent-0.9.30.sigs
new file mode 100644
index 0000000..9b8bfa1
--- /dev/null
+++ b/lib/tevent/ABI/tevent-0.9.30.sigs
@@ -0,0 +1,96 @@
+_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
+_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
+_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
+_tevent_loop_once: int (struct tevent_context *, const char *)
+_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
+_tevent_loop_wait: int (struct tevent_context *, const char *)
+_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
+_tevent_req_callback_data: void *(struct tevent_req *)
+_tevent_req_cancel: bool (struct tevent_req *, const char *)
+_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
+_tevent_req_data: void *(struct tevent_req *)
+_tevent_req_done: void (struct tevent_req *, const char *)
+_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
+_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
+_tevent_req_notify_callback: void (struct tevent_req *, const char *)
+_tevent_req_oom: void (struct tevent_req *, const char *)
+_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+_tevent_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_backend_list: const char **(TALLOC_CTX *)
+tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
+tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
+tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
+tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_check_signal: int (struct tevent_context *)
+tevent_common_context_destructor: int (struct tevent_context *)
+tevent_common_fd_destructor: int (struct tevent_fd *)
+tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
+tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
+tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
+tevent_common_have_events: bool (struct tevent_context *)
+tevent_common_loop_immediate: bool (struct tevent_context *)
+tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
+tevent_common_loop_wait: int (struct tevent_context *, const char *)
+tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_common_threaded_activate_immediate: void (struct tevent_context *)
+tevent_common_wakeup: int (struct tevent_context *)
+tevent_common_wakeup_init: int (struct tevent_context *)
+tevent_context_init: struct tevent_context *(TALLOC_CTX *)
+tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
+tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *)
+tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
+tevent_fd_get_flags: uint16_t (struct tevent_fd *)
+tevent_fd_set_auto_close: void (struct tevent_fd *)
+tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
+tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
+tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *)
+tevent_loop_allow_nesting: void (struct tevent_context *)
+tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
+tevent_num_signals: size_t (void)
+tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_length: size_t (struct tevent_queue *)
+tevent_queue_running: bool (struct tevent_queue *)
+tevent_queue_start: void (struct tevent_queue *)
+tevent_queue_stop: void (struct tevent_queue *)
+tevent_queue_wait_recv: bool (struct tevent_req *)
+tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct tevent_queue *)
+tevent_re_initialise: int (struct tevent_context *)
+tevent_register_backend: bool (const char *, const struct tevent_ops *)
+tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
+tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *)
+tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
+tevent_req_is_in_progress: bool (struct tevent_req *)
+tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
+tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
+tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
+tevent_req_received: void (struct tevent_req *)
+tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
+tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
+tevent_req_set_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_fn)
+tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
+tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
+tevent_sa_info_queue_count: size_t (void)
+tevent_set_abort_fn: void (void (*)(const char *))
+tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
+tevent_set_debug_stderr: int (struct tevent_context *)
+tevent_set_default_backend: void (const char *)
+tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *)
+tevent_signal_support: bool (struct tevent_context *)
+tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *)
+tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *)
+tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *)
+tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
+tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
+tevent_timeval_current: struct timeval (void)
+tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
+tevent_timeval_is_zero: bool (const struct timeval *)
+tevent_timeval_set: struct timeval (uint32_t, uint32_t)
+tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
+tevent_timeval_zero: struct timeval (void)
+tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point)
+tevent_wakeup_recv: bool (struct tevent_req *)
+tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)
diff --git a/lib/tevent/ABI/tevent-0.9.31.sigs b/lib/tevent/ABI/tevent-0.9.31.sigs
new file mode 100644
index 0000000..7a6a236
--- /dev/null
+++ b/lib/tevent/ABI/tevent-0.9.31.sigs
@@ -0,0 +1,99 @@
+_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
+_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
+_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
+_tevent_loop_once: int (struct tevent_context *, const char *)
+_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
+_tevent_loop_wait: int (struct tevent_context *, const char *)
+_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
+_tevent_req_callback_data: void *(struct tevent_req *)
+_tevent_req_cancel: bool (struct tevent_req *, const char *)
+_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
+_tevent_req_data: void *(struct tevent_req *)
+_tevent_req_done: void (struct tevent_req *, const char *)
+_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
+_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
+_tevent_req_notify_callback: void (struct tevent_req *, const char *)
+_tevent_req_oom: void (struct tevent_req *, const char *)
+_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+_tevent_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_backend_list: const char **(TALLOC_CTX *)
+tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
+tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
+tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
+tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_check_signal: int (struct tevent_context *)
+tevent_common_context_destructor: int (struct tevent_context *)
+tevent_common_fd_destructor: int (struct tevent_fd *)
+tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
+tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
+tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
+tevent_common_have_events: bool (struct tevent_context *)
+tevent_common_loop_immediate: bool (struct tevent_context *)
+tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
+tevent_common_loop_wait: int (struct tevent_context *, const char *)
+tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_common_threaded_activate_immediate: void (struct tevent_context *)
+tevent_common_wakeup: int (struct tevent_context *)
+tevent_common_wakeup_fd: int (int)
+tevent_common_wakeup_init: int (struct tevent_context *)
+tevent_context_init: struct tevent_context *(TALLOC_CTX *)
+tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
+tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *)
+tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
+tevent_fd_get_flags: uint16_t (struct tevent_fd *)
+tevent_fd_set_auto_close: void (struct tevent_fd *)
+tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
+tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
+tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *)
+tevent_loop_allow_nesting: void (struct tevent_context *)
+tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
+tevent_num_signals: size_t (void)
+tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
+tevent_queue_length: size_t (struct tevent_queue *)
+tevent_queue_running: bool (struct tevent_queue *)
+tevent_queue_start: void (struct tevent_queue *)
+tevent_queue_stop: void (struct tevent_queue *)
+tevent_queue_wait_recv: bool (struct tevent_req *)
+tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct tevent_queue *)
+tevent_re_initialise: int (struct tevent_context *)
+tevent_register_backend: bool (const char *, const struct tevent_ops *)
+tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
+tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *)
+tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
+tevent_req_is_in_progress: bool (struct tevent_req *)
+tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
+tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
+tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
+tevent_req_received: void (struct tevent_req *)
+tevent_req_reset_endtime: void (struct tevent_req *)
+tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
+tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
+tevent_req_set_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_fn)
+tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
+tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
+tevent_sa_info_queue_count: size_t (void)
+tevent_set_abort_fn: void (void (*)(const char *))
+tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
+tevent_set_debug_stderr: int (struct tevent_context *)
+tevent_set_default_backend: void (const char *)
+tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *)
+tevent_signal_support: bool (struct tevent_context *)
+tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *)
+tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *)
+tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *)
+tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
+tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
+tevent_timeval_current: struct timeval (void)
+tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
+tevent_timeval_is_zero: bool (const struct timeval *)
+tevent_timeval_set: struct timeval (uint32_t, uint32_t)
+tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
+tevent_timeval_zero: struct timeval (void)
+tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point)
+tevent_update_timer: void (struct tevent_timer *, struct timeval)
+tevent_wakeup_recv: bool (struct tevent_req *)
+tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)
diff --git a/lib/tevent/doc/tevent_context.dox b/lib/tevent/doc/tevent_context.dox
index 1036d3c..39eb85e 100644
--- a/lib/tevent/doc/tevent_context.dox
+++ b/lib/tevent/doc/tevent_context.dox
@@ -67,7 +67,7 @@ event again. There are 2 types of loop available for use in tevent library:
<li>int tevent_loop_once()</li>
</ul>
-Both of functions accept just one parametr (tevent context) and the only
+Both of functions accept just one parameter (tevent context) and the only
difference lies in the fact that the first loop can theoretically last for ever
but the second one will wait just for a single one event to catch and then the
loop breaks and the program continue.
diff --git a/lib/tevent/doc/tevent_queue.dox b/lib/tevent/doc/tevent_queue.dox
index fef98c8..9c247e5 100644
--- a/lib/tevent/doc/tevent_queue.dox
+++ b/lib/tevent/doc/tevent_queue.dox
@@ -11,7 +11,8 @@ beginning of the queue as fast as possible. In tevent library it is
similar, but the queue is not automatically set for any event. The queue has to
be created on purpose, and events which should follow the order of the FIFO
queue have to be explicitly pinpointed. Creating such a queue is crucial in
-situations when sequential processing is absolutely essential for the succesful
+situations when sequential processing is absolutely essential for the
+successful
completion of a task, e.g. for a large quantity of data that are about to be
written from a buffer into a socket. The tevent library has its own queue
structure that is ready to use after it has been initialized and started up
@@ -20,7 +21,7 @@ once.
@subsection cr_queue Creation of Queues
The first and most important step is the creation of the tevent queue
-(represented by struct tevent queue), which will then be in running mode.
+(represented by struct tevent_queue), which will then be in running mode.
@code
struct tevent_queue* tevent_queue_create (TALLOC_CTX *mem_ctx, const char *name)
diff --git a/lib/tevent/doc/tevent_thread.dox b/lib/tevent/doc/tevent_thread.dox
index 7b45820..875dae8 100644
--- a/lib/tevent/doc/tevent_thread.dox
+++ b/lib/tevent/doc/tevent_thread.dox
@@ -1,7 +1,7 @@
/**
-@page tevent_context Chapter 6: Tevent with threads
+@page tevent_thread Chapter 6: Tevent with threads
-@section context Tevent with threads
+@section threads Tevent with threads
In order to use tevent with threads, you must first understand
how to use the talloc library in threaded programs. For more
diff --git a/lib/tevent/echo_server.c b/lib/tevent/echo_server.c
index 102f7b4..6e7f181 100644
--- a/lib/tevent/echo_server.c
+++ b/lib/tevent/echo_server.c
@@ -66,7 +66,7 @@ struct accept_state {
struct tevent_fd *fde;
int listen_sock;
socklen_t addrlen;
- struct sockaddr addr;
+ struct sockaddr_storage addr;
int sock;
};
@@ -111,7 +111,9 @@ static void accept_handler(struct tevent_context *ev, struct tevent_fd *fde,
}
state->addrlen = sizeof(state->addr);
- ret = accept(state->listen_sock, &state->addr, &state->addrlen);
+ ret = accept(state->listen_sock,
+ (struct sockaddr *)&state->addr,
+ &state->addrlen);
if (ret == -1) {
tevent_req_error(req, errno);
return;
@@ -133,7 +135,7 @@ static int accept_recv(struct tevent_req *req, struct sockaddr *paddr,
return -1;
}
if (paddr != NULL) {
- *paddr = state->addr;
+ memcpy(paddr, &state->addr, state->addrlen);
}
if (paddrlen != NULL) {
*paddrlen = state->addrlen;
diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c
index bcd27fd..4783ab4 100644
--- a/lib/tevent/testsuite.c
+++ b/lib/tevent/testsuite.c
@@ -38,6 +38,15 @@
static int fde_count;
+static void do_read(int fd, void *buf, size_t count)
+{
+ ssize_t ret;
+
+ do {
+ ret = read(fd, buf, count);
+ } while (ret == -1 && errno == EINTR);
+}
+
static void fde_handler_read(struct tevent_context *ev_ctx, struct tevent_fd *f,
uint16_t flags, void *private_data)
{
@@ -48,16 +57,26 @@ static void fde_handler_read(struct tevent_context *ev_ctx, struct tevent_fd *f,
#endif
kill(getpid(), SIGALRM);
- read(fd[0], &c, 1);
+ do_read(fd[0], &c, 1);
fde_count++;
}
+static void do_write(int fd, void *buf, size_t count)
+{
+ ssize_t ret;
+
+ do {
+ ret = write(fd, buf, count);
+ } while (ret == -1 && errno == EINTR);
+}
+
static void fde_handler_write(struct tevent_context *ev_ctx, struct tevent_fd *f,
uint16_t flags, void *private_data)
{
int *fd = (int *)private_data;
char c = 0;
- write(fd[1], &c, 1);
+
+ do_write(fd[1], &c, 1);
}
@@ -72,7 +91,7 @@ static void fde_handler_read_1(struct tevent_context *ev_ctx, struct tevent_fd *
#endif
kill(getpid(), SIGALRM);
- read(fd[1], &c, 1);
+ do_read(fd[1], &c, 1);
fde_count++;
}
@@ -82,7 +101,7 @@ static void fde_handler_write_1(struct tevent_context *ev_ctx, struct tevent_fd
{
int *fd = (int *)private_data;
char c = 0;
- write(fd[0], &c, 1);
+ do_write(fd[0], &c, 1);
}
static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te,
@@ -281,7 +300,7 @@ static void test_event_fd1_fde_handler(struct tevent_context *ev_ctx,
/*
* we write to the other socket...
*/
- write(state->sock[1], &c, 1);
+ do_write(state->sock[1], &c, 1);
TEVENT_FD_NOT_WRITEABLE(fde);
TEVENT_FD_READABLE(fde);
return;
@@ -650,9 +669,9 @@ static bool test_event_fd2(struct torture_context *tctx,
tevent_fd_set_auto_close(state.sock0.fde);
tevent_fd_set_auto_close(state.sock1.fde);
- write(state.sock0.fd, &c, 1);
+ do_write(state.sock0.fd, &c, 1);
state.sock0.num_written++;
- write(state.sock1.fd, &c, 1);
+ do_write(state.sock1.fd, &c, 1);
state.sock1.num_written++;
while (!state.finished) {
@@ -792,7 +811,7 @@ static bool test_event_context_threaded(struct torture_context *test,
poll(NULL, 0, 100);
- write(fds[1], &c, 1);
+ do_write(fds[1], &c, 1);
poll(NULL, 0, 100);
@@ -800,7 +819,7 @@ static bool test_event_context_threaded(struct torture_context *test,
do_shutdown = true;
test_event_threaded_unlock();
- write(fds[1], &c, 1);
+ do_write(fds[1], &c, 1);
ret = pthread_join(poll_thread, NULL);
torture_assert(test, ret == 0, "pthread_join failed");
@@ -1129,6 +1148,101 @@ static bool test_multi_tevent_threaded_1(struct torture_context *test,
talloc_free(master_ev);
return true;
}
+
+struct threaded_test_2 {
+ struct tevent_threaded_context *tctx;
+ struct tevent_immediate *im;
+ pthread_t thread_id;
+};
+
+static void master_callback_2(struct tevent_context *ev,
+ struct tevent_immediate *im,
+ void *private_data);
+
+static void *thread_fn_2(void *private_data)
+{
+ struct threaded_test_2 *state = private_data;
+
+ state->thread_id = pthread_self();
+
+ usleep(random() % 7000);
+
+ tevent_threaded_schedule_immediate(
+ state->tctx, state->im, master_callback_2, state);
+
+ return NULL;
+}
+
+static void master_callback_2(struct tevent_context *ev,
+ struct tevent_immediate *im,
+ void *private_data)
+{
+ struct threaded_test_2 *state = private_data;
+ int i;
+
+ for (i = 0; i < NUM_TEVENT_THREADS; i++) {
+ if (pthread_equal(state->thread_id, thread_map[i])) {
+ break;
+ }
+ }
+ torture_comment(thread_test_ctx,
+ "Callback_2 %u from thread %u\n",
+ thread_counter,
+ i);
+ thread_counter++;
+}
+
+static bool test_multi_tevent_threaded_2(struct torture_context *test,
+ const void *test_data)
+{
+ unsigned i;
+
+ struct tevent_context *ev;
+ struct tevent_threaded_context *tctx;
+ int ret;
+
+ thread_test_ctx = test;
+ thread_counter = 0;
+
+ ev = tevent_context_init(test);
+ torture_assert(test, ev != NULL, "tevent_context_init failed");
+
+ tctx = tevent_threaded_context_create(ev, ev);
+ torture_assert(test, tctx != NULL,
+ "tevent_threaded_context_create failed");
+
+ for (i=0; i<NUM_TEVENT_THREADS; i++) {
+ struct threaded_test_2 *state;
+
+ state = talloc(ev, struct threaded_test_2);
+ torture_assert(test, state != NULL, "talloc failed");
+
+ state->tctx = tctx;
+ state->im = tevent_create_immediate(state);
+ torture_assert(test, state->im != NULL,
+ "tevent_create_immediate failed");
+
+ ret = pthread_create(&thread_map[i], NULL, thread_fn_2, state);
+ torture_assert(test, ret == 0, "pthread_create failed");
+ }
+
+ while (thread_counter < NUM_TEVENT_THREADS) {
+ ret = tevent_loop_once(ev);
+ torture_assert(test, ret == 0, "tevent_loop_once failed");
+ }
+
+ /* Wait for all the threads to finish - join 'em. */
+ for (i = 0; i < NUM_TEVENT_THREADS; i++) {
+ void *retval;
+ ret = pthread_join(thread_map[i], &retval);
+ torture_assert(test, ret == 0, "pthread_join failed");
+ /* Free the child thread event context. */
+ }
+
+ talloc_free(tctx);
+ talloc_free(ev);
+ return true;
+}
#endif
struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
@@ -1171,6 +1285,10 @@ struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
test_multi_tevent_threaded_1,
NULL);
+ torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_2",
+ test_multi_tevent_threaded_2,
+ NULL);
+
#endif
return suite;
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c
index 843cf05..65b101f 100644
--- a/lib/tevent/tevent.c
+++ b/lib/tevent/tevent.c
@@ -59,10 +59,18 @@
*/
#include "replace.h"
#include "system/filesys.h"
+#ifdef HAVE_PTHREAD
+#include "system/threads.h"
+#endif
#define TEVENT_DEPRECATED 1
#include "tevent.h"
#include "tevent_internal.h"
#include "tevent_util.h"
+#ifdef HAVE_EVENTFD
+#include <sys/eventfd.h>
+#endif
+
+static void tevent_abort(struct tevent_context *ev, const char *reason);
struct tevent_ops_list {
struct tevent_ops_list *next, *prev;
@@ -173,6 +181,120 @@ const char **tevent_backend_list(TALLOC_CTX *mem_ctx)
return list;
}
+static void tevent_common_wakeup_fini(struct tevent_context *ev);
+
+#ifdef HAVE_PTHREAD
+
+static pthread_mutex_t tevent_contexts_mutex = PTHREAD_MUTEX_INITIALIZER;
+static struct tevent_context *tevent_contexts = NULL;
+static pthread_once_t tevent_atfork_initialized = PTHREAD_ONCE_INIT;
+
+static void tevent_atfork_prepare(void)
+{
+ struct tevent_context *ev;
+ int ret;
+
+ ret = pthread_mutex_lock(&tevent_contexts_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+ for (ev = tevent_contexts; ev != NULL; ev = ev->next) {
+ struct tevent_threaded_context *tctx;
+
+ for (tctx = ev->threaded_contexts; tctx != NULL;
+ tctx = tctx->next) {
+ ret = pthread_mutex_lock(&tctx->event_ctx_mutex);
+ if (ret != 0) {
+ tevent_abort(ev, "pthread_mutex_lock failed");
+ }
+ }
+
+ ret = pthread_mutex_lock(&ev->scheduled_mutex);
+ if (ret != 0) {
+ tevent_abort(ev, "pthread_mutex_lock failed");
+ }
+ }
+}
+
+static void tevent_atfork_parent(void)
+{
+ struct tevent_context *ev;
+ int ret;
+
+ for (ev = DLIST_TAIL(tevent_contexts); ev != NULL;
+ ev = DLIST_PREV(ev)) {
+ struct tevent_threaded_context *tctx;
+
+ ret = pthread_mutex_unlock(&ev->scheduled_mutex);
+ if (ret != 0) {
+ tevent_abort(ev, "pthread_mutex_unlock failed");
+ }
+
+ for (tctx = DLIST_TAIL(ev->threaded_contexts); tctx != NULL;
+ tctx = DLIST_PREV(tctx)) {
+ ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
+ if (ret != 0) {
+ tevent_abort(
+ ev, "pthread_mutex_unlock failed");
+ }
+ }
+ }
+
+ ret = pthread_mutex_unlock(&tevent_contexts_mutex);
+ if (ret != 0) {
+ abort();
+ }
+}
+
+static void tevent_atfork_child(void)
+{
+ struct tevent_context *ev;
+ int ret;
+
+ for (ev = DLIST_TAIL(tevent_contexts); ev != NULL;
+ ev = DLIST_PREV(ev)) {
+ struct tevent_threaded_context *tctx;
+
+ for (tctx = DLIST_TAIL(ev->threaded_contexts); tctx != NULL;
+ tctx = DLIST_PREV(tctx)) {
+ tctx->event_ctx = NULL;
+
+ ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
+ if (ret != 0) {
+ tevent_abort(
+ ev, "pthread_mutex_unlock failed");
+ }
+ }
+
+ ev->threaded_contexts = NULL;
+
+ ret = pthread_mutex_unlock(&ev->scheduled_mutex);
+ if (ret != 0) {
+ tevent_abort(ev, "pthread_mutex_unlock failed");
+ }
+ }
+
+ ret = pthread_mutex_unlock(&tevent_contexts_mutex);
+ if (ret != 0) {
+ abort();
+ }
+}
+
+static void tevent_prep_atfork(void)
+{
+ int ret;
+
+ ret = pthread_atfork(tevent_atfork_prepare,
+ tevent_atfork_parent,
+ tevent_atfork_child);
+ if (ret != 0) {
+ abort();
+ }
+}
+
+#endif
+
int tevent_common_context_destructor(struct tevent_context *ev)
{
struct tevent_fd *fd, *fn;
@@ -180,13 +302,49 @@ int tevent_common_context_destructor(struct tevent_context *ev)
struct tevent_immediate *ie, *in;
struct tevent_signal *se, *sn;
- if (ev->pipe_fde) {
- talloc_free(ev->pipe_fde);
- close(ev->pipe_fds[0]);
- close(ev->pipe_fds[1]);
- ev->pipe_fde = NULL;
+#ifdef HAVE_PTHREAD
+ int ret;
+
+ ret = pthread_mutex_lock(&tevent_contexts_mutex);
+ if (ret != 0) {
+ abort();
}
+ DLIST_REMOVE(tevent_contexts, ev);
+
+ ret = pthread_mutex_unlock(&tevent_contexts_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+ while (ev->threaded_contexts != NULL) {
+ struct tevent_threaded_context *tctx = ev->threaded_contexts;
+
+ ret = pthread_mutex_lock(&tctx->event_ctx_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+ /*
+ * Indicate to the thread that the tevent_context is
+ * gone. The counterpart of this is in
+ * _tevent_threaded_schedule_immediate, there we read
+ * this under the threaded_context's mutex.
+ */
+
+ tctx->event_ctx = NULL;
+
+ ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+ DLIST_REMOVE(ev->threaded_contexts, tctx);
+ }
+#endif
+
+ tevent_common_wakeup_fini(ev);
+
for (fd = ev->fd_events; fd; fd = fn) {
fn = fd->next;
fd->event_ctx = NULL;
@@ -255,6 +413,36 @@ struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
ev = talloc_zero(mem_ctx, struct tevent_context);
if (!ev) return NULL;
+#ifdef HAVE_PTHREAD
+
+ ret = pthread_once(&tevent_atfork_initialized, tevent_prep_atfork);
+ if (ret != 0) {
+ talloc_free(ev);
+ return NULL;
+ }
+
+ ret = pthread_mutex_init(&ev->scheduled_mutex, NULL);
+ if (ret != 0) {
+ talloc_free(ev);
+ return NULL;
+ }
+
+ ret = pthread_mutex_lock(&tevent_contexts_mutex);
+ if (ret != 0) {
+ pthread_mutex_destroy(&ev->scheduled_mutex);
+ talloc_free(ev);
+ return NULL;
+ }
+
+ DLIST_ADD(tevent_contexts, ev);
+
+ ret = pthread_mutex_unlock(&tevent_contexts_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+#endif
+
talloc_set_destructor(ev, tevent_common_context_destructor);
ev->ops = ops;
@@ -620,6 +808,28 @@ done:
return ret;
}
+bool tevent_common_have_events(struct tevent_context *ev)
+{
+ if (ev->fd_events != NULL) {
+ if (ev->fd_events != ev->wakeup_fde) {
+ return true;
+ }
+ if (ev->fd_events->next != NULL) {
+ return true;
+ }
+
+ /*
+ * At this point we just have the wakeup pipe event as
+ * the only fd_event. That one does not count as a
+ * regular event, so look at the other event types.
+ */
+ }
+
+ return ((ev->timer_events != NULL) ||
+ (ev->immediate_events != NULL) ||
+ (ev->signal_events != NULL));
+}
+
/*
return on failure or (with 0) if all fd events are removed
*/
@@ -629,10 +839,7 @@ int tevent_common_loop_wait(struct tevent_context *ev,
/*
* loop as long as we have events pending
*/
- while (ev->fd_events ||
- ev->timer_events ||
- ev->immediate_events ||
- ev->signal_events) {
+ while (tevent_common_have_events(ev)) {
int ret;
ret = _tevent_loop_once(ev, location);
if (ret != 0) {
@@ -670,3 +877,108 @@ int tevent_re_initialise(struct tevent_context *ev)
return ev->ops->context_init(ev);
}
+
+static void wakeup_pipe_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags, void *_private)
+{
+ ssize_t ret;
+
+ do {
+ /*
+ * This is the boilerplate for eventfd, but it works
+ * for pipes too. And as we don't care about the data
+ * we read, we're fine.
+ */
+ uint64_t val;
+ ret = read(fde->fd, &val, sizeof(val));
+ } while (ret == -1 && errno == EINTR);
+}
+
+/*
+ * Initialize the wakeup pipe and pipe fde
+ */
+
+int tevent_common_wakeup_init(struct tevent_context *ev)
+{
+ int ret, read_fd;
+
+ if (ev->wakeup_fde != NULL) {
+ return 0;
+ }
+
+#ifdef HAVE_EVENTFD
+ ret = eventfd(0, EFD_NONBLOCK);
+ if (ret == -1) {
+ return errno;
+ }
+ read_fd = ev->wakeup_fd = ret;
+#else
+ {
+ int pipe_fds[2];
+ ret = pipe(pipe_fds);
+ if (ret == -1) {
+ return errno;
+ }
+ ev->wakeup_fd = pipe_fds[1];
+ ev->wakeup_read_fd = pipe_fds[0];
+
+ ev_set_blocking(ev->wakeup_fd, false);
+ ev_set_blocking(ev->wakeup_read_fd, false);
+
+ read_fd = ev->wakeup_read_fd;
+ }
+#endif
+
+ ev->wakeup_fde = tevent_add_fd(ev, ev, read_fd, TEVENT_FD_READ,
+ wakeup_pipe_handler, NULL);
+ if (ev->wakeup_fde == NULL) {
+ close(ev->wakeup_fd);
+#ifndef HAVE_EVENTFD
+ close(ev->wakeup_read_fd);
+#endif
+ return ENOMEM;
+ }
+
+ return 0;
+}
+
+int tevent_common_wakeup_fd(int fd)
+{
+ ssize_t ret;
+
+ do {
+#ifdef HAVE_EVENTFD
+ uint64_t val = 1;
+ ret = write(fd, &val, sizeof(val));
+#else
+ char c = '\0';
+ ret = write(fd, &c, 1);
+#endif
+ } while ((ret == -1) && (errno == EINTR));
+
+ return 0;
+}
+
+int tevent_common_wakeup(struct tevent_context *ev)
+{
+ if (ev->wakeup_fde == NULL) {
+ return ENOTCONN;
+ }
+
+ return tevent_common_wakeup_fd(ev->wakeup_fd);
+}
+
+static void tevent_common_wakeup_fini(struct tevent_context *ev)
+{
+ if (ev->wakeup_fde == NULL) {
+ return;
+ }
+
+ TALLOC_FREE(ev->wakeup_fde);
+
+ close(ev->wakeup_fd);
+#ifndef HAVE_EVENTFD
+ close(ev->wakeup_read_fd);
+#endif
+}
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index cb95507..ba4bb4d 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -40,6 +40,7 @@ struct tevent_timer;
struct tevent_immediate;
struct tevent_signal;
struct tevent_thread_proxy;
+struct tevent_threaded_context;
/**
* @defgroup tevent The tevent API
@@ -251,6 +252,16 @@ struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
#handler, __location__)
#endif
+/**
+ * @brief Set the time a tevent_timer fires
+ *
+ * @param[in] te The timer event to reset
+ *
+ * @param[in] next_event Timeval specifying the absolute time to fire this
+ * event. This is not an offset.
+ */
+void tevent_update_timer(struct tevent_timer *te, struct timeval next_event);
+
#ifdef DOXYGEN
/**
* Initialize an immediate event object
@@ -464,11 +475,11 @@ void tevent_set_abort_fn(void (*abort_fn)(const char *reason));
/* bits for file descriptor event flags */
/**
- * Monitor a file descriptor for write availability
+ * Monitor a file descriptor for data to be read
*/
#define TEVENT_FD_READ 1
/**
- * Monitor a file descriptor for data to be read
+ * Monitor a file descriptor for writeability
*/
#define TEVENT_FD_WRITE 2
@@ -1029,6 +1040,13 @@ bool tevent_req_set_endtime(struct tevent_req *req,
struct tevent_context *ev,
struct timeval endtime);
+/**
+ * @brief Reset the timer set by tevent_req_set_endtime.
+ *
+ * @param[in] req The request to reset the timeout for
+ */
+void tevent_req_reset_endtime(struct tevent_req *req);
+
#ifdef DOXYGEN
/**
* @brief Call the notify callback of the given tevent request manually.
@@ -1369,7 +1387,7 @@ bool tevent_wakeup_recv(struct tevent_req *req);
/* @} */
/**
- * @defgroup tevent_helpers The tevent helper functiions
+ * @defgroup tevent_helpers The tevent helper functions
* @ingroup tevent
*
* @todo description
@@ -1392,16 +1410,16 @@ int tevent_timeval_compare(const struct timeval *tv1,
const struct timeval *tv2);
/**
- * @brief Get a zero timval value.
+ * @brief Get a zero timeval value.
*
- * @return A zero timval value.
+ * @return A zero timeval value.
*/
struct timeval tevent_timeval_zero(void);
/**
* @brief Get a timeval value for the current time.
*
- * @return A timval value with the current time.
+ * @return A timeval value with the current time.
*/
struct timeval tevent_timeval_current(void);
@@ -1750,9 +1768,82 @@ void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp,
tevent_immediate_handler_t handler,
void *pp_private_data);
+/*
+ * @brief Create a context for threaded activation of immediates
+ *
+ * A tevent_treaded_context provides a link into an event
+ * context. Using tevent_threaded_schedule_immediate, it is possible
+ * to activate an immediate event from within a thread.
+ *
+ * It is the duty of the caller of tevent_threaded_context_create() to
+ * keep the event context around longer than any
+ * tevent_threaded_context. tevent will abort if ev is talllc_free'ed
+ * with an active tevent_threaded_context.
+ *
+ * If tevent is build without pthread support, this always returns
+ * NULL with errno=ENOSYS.
+ *
+ * @param[in] mem_ctx The talloc memory context to use.
+ * @param[in] ev The event context to link this to.
+ * @return The threaded context, or NULL with errno set.
+ *
+ * @see tevent_threaded_schedule_immediate()
+ *
+ * @note Available as of tevent 0.9.30
+ */
+struct tevent_threaded_context *tevent_threaded_context_create(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev);
+
+#ifdef DOXYGEN
+/*
+ * @brief Activate an immediate from a thread
+ *
+ * Activate an immediate from within a thread.
+ *
+ * This routine does not watch out for talloc hierarchies. This means
+ * that it is highly recommended to create the tevent_immediate in the
+ * thread owning tctx, allocate a threaded job description for the
+ * thread, hand over both pointers to a helper thread and not touch it
+ * in the main thread at all anymore.
+ *
+ * tevent_threaded_schedule_immediate is intended as a job completion
+ * indicator for simple threaded helpers.
+ *
+ * Please be aware that tevent_threaded_schedule_immediate is very
+ * picky about its arguments: An immediate may not already be
+ * activated and the handler must exist. With
+ * tevent_threaded_schedule_immediate memory ownership is transferred
+ * to the main thread holding the tevent context behind tctx, the
+ * helper thread can't access it anymore.
+ *
+ * @param[in] tctx The threaded context to go through
+ * @param[in] im The immediate event to activate
+ * @param[in] handler The immediate handler to call in the main thread
+ * @param[in] private_data Pointer for the immediate handler
+ *
+ * @see tevent_threaded_context_create()
+ *
+ * @note Available as of tevent 0.9.30
+ */
+void tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx,
+ struct tevent_immediate *im,
+ tevent_immediate_handler_t handler,
+ void *private_data);
+#else
+void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx,
+ struct tevent_immediate *im,
+ tevent_immediate_handler_t handler,
+ void *private_data,
+ const char *handler_name,
+ const char *location);
+#define tevent_threaded_schedule_immediate(tctx, im, handler, private_data) \
+ _tevent_threaded_schedule_immediate(tctx, im, handler, private_data, \
+ #handler, __location__);
+#endif
+
#ifdef TEVENT_DEPRECATED
#ifndef _DEPRECATED_
-#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 )
+#ifdef HAVE___ATTRIBUTE__
#define _DEPRECATED_ __attribute__ ((deprecated))
#else
#define _DEPRECATED_
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 507ea5c..4147c67 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -903,6 +903,10 @@ static int epoll_event_loop_once(struct tevent_context *ev, const char *location
return 0;
}
+ if (ev->threaded_contexts != NULL) {
+ tevent_common_threaded_activate_immediate(ev);
+ }
+
if (ev->immediate_events &&
tevent_common_loop_immediate(ev)) {
return 0;
diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h
index 10cc4a4..a5f1ebd 100644
--- a/lib/tevent/tevent_internal.h
+++ b/lib/tevent/tevent_internal.h
@@ -228,6 +228,16 @@ struct tevent_signal {
void *additional_data;
};
+struct tevent_threaded_context {
+ struct tevent_threaded_context *next, *prev;
+
+#ifdef HAVE_PTHREAD
+ pthread_mutex_t event_ctx_mutex;
+#endif
+ struct tevent_context *event_ctx;
+ int wakeup_fd;
+};
+
struct tevent_debug_ops {
void (*debug)(void *context, enum tevent_debug_level level,
const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
@@ -241,24 +251,41 @@ struct tevent_context {
/* the specific events implementation */
const struct tevent_ops *ops;
+ /*
+ * The following three pointers are queried on every loop_once
+ * in the order in which they appear here. Not measured, but
+ * hopefully putting them at the top together with "ops"
+ * should make tevent a *bit* more cache-friendly than before.
+ */
+
+ /* list of signal events - used by common code */
+ struct tevent_signal *signal_events;
+
+ /* List of threaded job indicators */
+ struct tevent_threaded_context *threaded_contexts;
+
+ /* list of immediate events - used by common code */
+ struct tevent_immediate *immediate_events;
+
/* list of fd events - used by common code */
struct tevent_fd *fd_events;
/* list of timed events - used by common code */
struct tevent_timer *timer_events;
- /* list of immediate events - used by common code */
- struct tevent_immediate *immediate_events;
-
- /* list of signal events - used by common code */
- struct tevent_signal *signal_events;
+ /* List of scheduled immediates */
+ pthread_mutex_t scheduled_mutex;
+ struct tevent_immediate *scheduled_immediates;
/* this is private for the events_ops implementation */
void *additional_data;
/* pipe hack used with signal handlers */
- struct tevent_fd *pipe_fde;
- int pipe_fds[2];
+ struct tevent_fd *wakeup_fde;
+ int wakeup_fd; /* fd to write into */
+#ifndef HAVE_EVENT_FD
+ int wakeup_read_fd;
+#endif
/* debugging operations */
struct tevent_debug_ops debug_ops;
@@ -282,6 +309,10 @@ struct tevent_context {
* tevent_common_add_timer_v2()
*/
struct tevent_timer *last_zero_timer;
+
+#ifdef HAVE_PTHREAD
+ struct tevent_context *prev, *next;
+#endif
};
const struct tevent_ops *tevent_find_ops_byname(const char *name);
@@ -327,6 +358,12 @@ void tevent_common_schedule_immediate(struct tevent_immediate *im,
const char *handler_name,
const char *location);
bool tevent_common_loop_immediate(struct tevent_context *ev);
+void tevent_common_threaded_activate_immediate(struct tevent_context *ev);
+
+bool tevent_common_have_events(struct tevent_context *ev);
+int tevent_common_wakeup_init(struct tevent_context *ev);
+int tevent_common_wakeup_fd(int fd);
+int tevent_common_wakeup(struct tevent_context *ev);
struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c
index e1c305d..09d85fa 100644
--- a/lib/tevent/tevent_poll.c
+++ b/lib/tevent/tevent_poll.c
@@ -645,6 +645,10 @@ static int poll_event_loop_once(struct tevent_context *ev,
return 0;
}
+ if (ev->threaded_contexts != NULL) {
+ tevent_common_threaded_activate_immediate(ev);
+ }
+
if (ev->immediate_events &&
tevent_common_loop_immediate(ev)) {
return 0;
@@ -667,10 +671,7 @@ static int poll_event_loop_wait(struct tevent_context *ev,
/*
* loop as long as we have events pending
*/
- while (ev->fd_events ||
- ev->timer_events ||
- ev->immediate_events ||
- ev->signal_events ||
+ while (tevent_common_have_events(ev) ||
poll_ev->fresh ||
poll_ev->disabled) {
int ret;
diff --git a/lib/tevent/tevent_port.c b/lib/tevent/tevent_port.c
index 4b524df..8cf9fd1 100644
--- a/lib/tevent/tevent_port.c
+++ b/lib/tevent/tevent_port.c
@@ -760,6 +760,10 @@ static int port_event_loop_once(struct tevent_context *ev, const char *location)
return 0;
}
+ if (ev->threaded_contexts != NULL) {
+ tevent_common_threaded_activate_immediate(ev);
+ }
+
if (ev->immediate_events &&
tevent_common_loop_immediate(ev)) {
return 0;
diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c
index cefe91a..5516c6c 100644
--- a/lib/tevent/tevent_queue.c
+++ b/lib/tevent/tevent_queue.c
@@ -187,7 +187,7 @@ static struct tevent_queue_entry *tevent_queue_add_internal(
if (req->async.fn != NULL) {
/*
- * If the callers wants to optimize for the
+ * If the caller wants to optimize for the
* empty queue case, call the trigger only
* if there is no callback defined for the
* request yet.
diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c
index c86fb68..e309c3d 100644
--- a/lib/tevent/tevent_req.c
+++ b/lib/tevent/tevent_req.c
@@ -62,6 +62,13 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
struct tevent_req *req;
void **ppdata = (void **)pdata;
void *data;
+ size_t payload;
+
+ payload = sizeof(struct tevent_immediate) + data_size;
+ if (payload < sizeof(struct tevent_immediate)) {
+ /* overflow */
+ return NULL;
+ }
req = talloc_pooled_object(
mem_ctx, struct tevent_req, 2,
@@ -69,21 +76,22 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
if (req == NULL) {
return NULL;
}
- ZERO_STRUCTP(req);
- req->internal.private_type = type;
- req->internal.create_location = location;
- req->internal.state = TEVENT_REQ_IN_PROGRESS;
- req->internal.trigger = tevent_create_immediate(req);
- if (!req->internal.trigger) {
- talloc_free(req);
- return NULL;
- }
+
+ *req = (struct tevent_req) {
+ .internal.private_type = type,
+ .internal.create_location = location,
+ .internal.state = TEVENT_REQ_IN_PROGRESS,
+ .internal.trigger = tevent_create_immediate(req)
+ };
data = talloc_zero_size(req, data_size);
- if (data == NULL) {
- talloc_free(req);
- return NULL;
- }
+
+ /*
+ * No need to check for req->internal.trigger!=NULL or
+ * data!=NULL, this can't fail: talloc_pooled_object has
+ * already allocated sufficient memory.
+ */
+
talloc_set_name_const(data, type);
req->data = data;
@@ -305,6 +313,11 @@ bool tevent_req_set_endtime(struct tevent_req *req,
return true;
}
+void tevent_req_reset_endtime(struct tevent_req *req)
+{
+ TALLOC_FREE(req->internal.timer);
+}
+
void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt)
{
req->async.fn = fn;
diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c
index ec7565d..55dd0b6 100644
--- a/lib/tevent/tevent_select.c
+++ b/lib/tevent/tevent_select.c
@@ -244,6 +244,10 @@ static int select_event_loop_once(struct tevent_context *ev, const char *locatio
return 0;
}
+ if (ev->threaded_contexts != NULL) {
+ tevent_common_threaded_activate_immediate(ev);
+ }
+
if (ev->immediate_events &&
tevent_common_loop_immediate(ev)) {
return 0;
diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c
index 924dc05..c85e1c5 100644
--- a/lib/tevent/tevent_signal.c
+++ b/lib/tevent/tevent_signal.c
@@ -95,7 +95,6 @@ static uint32_t tevent_sig_count(struct tevent_sigcounter s)
*/
static void tevent_common_signal_handler(int signum)
{
- char c = 0;
struct tevent_common_signal_list *sl;
struct tevent_context *ev = NULL;
int saved_errno = errno;
@@ -107,8 +106,7 @@ static void tevent_common_signal_handler(int signum)
for (sl = sig_state->sig_handlers[signum]; sl; sl = sl->next) {
if (sl->se->event_ctx && sl->se->event_ctx != ev) {
ev = sl->se->event_ctx;
- /* doesn't matter if this pipe overflows */
- (void) write(ev->pipe_fds[1], &c, 1);
+ tevent_common_wakeup(ev);
}
}
@@ -194,16 +192,6 @@ static int tevent_signal_destructor(struct tevent_signal *se)
struct tevent_context *ev = se->event_ctx;
DLIST_REMOVE(ev->signal_events, se);
-
- if (ev->signal_events == NULL && ev->pipe_fde != NULL) {
- /*
- * This was the last signal. Destroy the pipe.
- */
- TALLOC_FREE(ev->pipe_fde);
-
- close(ev->pipe_fds[0]);
- close(ev->pipe_fds[1]);
- }
}
talloc_free(sl);
@@ -212,6 +200,7 @@ static int tevent_signal_destructor(struct tevent_signal *se)
/* restore old handler, if any */
if (sig_state->oldact[se->signum]) {
sigaction(se->signum, sig_state->oldact[se->signum], NULL);
+ talloc_free(sig_state->oldact[se->signum]);
sig_state->oldact[se->signum] = NULL;
}
#ifdef SA_SIGINFO
@@ -228,17 +217,6 @@ static int tevent_signal_destructor(struct tevent_signal *se)
}
/*
- this is part of the pipe hack needed to avoid the signal race condition
-*/
-static void signal_pipe_handler(struct tevent_context *ev, struct tevent_fd *fde,
- uint16_t flags, void *_private)
-{
- char c[16];
- /* its non-blocking, doesn't matter if we read too much */
- (void) read(fde->fd, c, sizeof(c));
-}
-
-/*
add a signal event
return NULL on failure (memory allocation error)
*/
@@ -254,6 +232,13 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
struct tevent_signal *se;
struct tevent_common_signal_list *sl;
sigset_t set, oldset;
+ int ret;
+
+ ret = tevent_common_wakeup_init(ev);
+ if (ret != 0) {
+ errno = ret;
+ return NULL;
+ }
if (signum >= TEVENT_NUM_SIGNALS) {
errno = EINVAL;
@@ -295,26 +280,6 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
return NULL;
}
- /* we need to setup the pipe hack handler if not already
- setup */
- if (ev->pipe_fde == NULL) {
- if (pipe(ev->pipe_fds) == -1) {
- talloc_free(se);
- return NULL;
- }
- ev_set_blocking(ev->pipe_fds[0], false);
- ev_set_blocking(ev->pipe_fds[1], false);
- ev->pipe_fde = tevent_add_fd(ev, ev, ev->pipe_fds[0],
- TEVENT_FD_READ,
- signal_pipe_handler, NULL);
- if (!ev->pipe_fde) {
- close(ev->pipe_fds[0]);
- close(ev->pipe_fds[1]);
- talloc_free(se);
- return NULL;
- }
- }
-
/* only install a signal handler if not already installed */
if (sig_state->sig_handlers[signum] == NULL) {
struct sigaction act;
@@ -342,6 +307,8 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
return NULL;
}
if (sigaction(signum, &act, sig_state->oldact[signum]) == -1) {
+ talloc_free(sig_state->oldact[signum]);
+ sig_state->oldact[signum] = NULL;
talloc_free(se);
return NULL;
}
@@ -505,6 +472,7 @@ void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se)
if (sig_state->sig_handlers[se->signum] == NULL) {
if (sig_state->oldact[se->signum]) {
sigaction(se->signum, sig_state->oldact[se->signum], NULL);
+ talloc_free(sig_state->oldact[se->signum]);
sig_state->oldact[se->signum] = NULL;
}
}
diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c
index a050901..30e9b91 100644
--- a/lib/tevent/tevent_standard.c
+++ b/lib/tevent/tevent_standard.c
@@ -112,6 +112,11 @@ static int std_event_loop_once(struct tevent_context *ev, const char *location)
int ret;
ret = glue->epoll_ops->loop_once(ev, location);
+ /*
+ * If the above hasn't panicked due to an epoll interface failure,
+ * std_fallback_to_poll() wasn't called, and hasn't cleared epoll_ops to
+ * signify fallback to poll_ops.
+ */
if (glue->epoll_ops != NULL) {
/* No fallback */
return ret;
@@ -138,6 +143,11 @@ static int std_event_loop_wait(struct tevent_context *ev, const char *location)
int ret;
ret = glue->epoll_ops->loop_wait(ev, location);
+ /*
+ * If the above hasn't panicked due to an epoll interface failure,
+ * std_fallback_to_poll() wasn't called, and hasn't cleared epoll_ops to
+ * signify fallback to poll_ops.
+ */
if (glue->epoll_ops != NULL) {
/* No fallback */
return ret;
diff --git a/lib/tevent/tevent_threads.c b/lib/tevent/tevent_threads.c
index 8d44e4f..8197323 100644
--- a/lib/tevent/tevent_threads.c
+++ b/lib/tevent/tevent_threads.c
@@ -108,7 +108,7 @@ static void schedule_immediate_functions(struct tevent_thread_proxy *tp)
if (tp->tofree_im_list != NULL) {
/*
* Once the current immediate events
- * are processed, we need to reshedule
+ * are processed, we need to reschedule
* ourselves to free them. This works
* as tevent_schedule_immediate()
* always adds events to the *END* of
@@ -310,6 +310,7 @@ void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp,
struct tevent_immediate_list *im_entry;
int ret;
char c;
+ ssize_t written;
ret = pthread_mutex_lock(&tp->mutex);
if (ret != 0) {
@@ -341,7 +342,9 @@ void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp,
/* And notify the dest_ev_ctx to wake up. */
c = '\0';
- (void)write(tp->write_fd, &c, 1);
+ do {
+ written = write(tp->write_fd, &c, 1);
+ } while (written == -1 && errno == EINTR);
end:
@@ -368,3 +371,156 @@ void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp,
;
}
#endif
+
+static int tevent_threaded_context_destructor(
+ struct tevent_threaded_context *tctx)
+{
+ int ret;
+
+ if (tctx->event_ctx != NULL) {
+ DLIST_REMOVE(tctx->event_ctx->threaded_contexts, tctx);
+ }
+
+ ret = pthread_mutex_destroy(&tctx->event_ctx_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+ return 0;
+}
+
+struct tevent_threaded_context *tevent_threaded_context_create(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev)
+{
+#ifdef HAVE_PTHREAD
+ struct tevent_threaded_context *tctx;
+ int ret;
+
+ ret = tevent_common_wakeup_init(ev);
+ if (ret != 0) {
+ errno = ret;
+ return NULL;
+ }
+
+ tctx = talloc(mem_ctx, struct tevent_threaded_context);
+ if (tctx == NULL) {
+ return NULL;
+ }
+ tctx->event_ctx = ev;
+ tctx->wakeup_fd = ev->wakeup_fd;
+
+ ret = pthread_mutex_init(&tctx->event_ctx_mutex, NULL);
+ if (ret != 0) {
+ TALLOC_FREE(tctx);
+ return NULL;
+ }
+
+ DLIST_ADD(ev->threaded_contexts, tctx);
+ talloc_set_destructor(tctx, tevent_threaded_context_destructor);
+
+ return tctx;
+#else
+ errno = ENOSYS;
+ return NULL;
+#endif
+}
+
+void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx,
+ struct tevent_immediate *im,
+ tevent_immediate_handler_t handler,
+ void *private_data,
+ const char *handler_name,
+ const char *location)
+{
+#ifdef HAVE_PTHREAD
+ struct tevent_context *ev;
+ int ret;
+
+ ret = pthread_mutex_lock(&tctx->event_ctx_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+ ev = tctx->event_ctx;
+
+ ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+ if (ev == NULL) {
+ /*
+ * Our event context is already gone.
+ */
+ return;
+ }
+
+ if ((im->event_ctx != NULL) || (handler == NULL)) {
+ abort();
+ }
+
+ im->event_ctx = ev;
+ im->handler = handler;
+ im->private_data = private_data;
+ im->handler_name = handler_name;
+ im->schedule_location = location;
+ im->cancel_fn = NULL;
+ im->additional_data = NULL;
+
+ ret = pthread_mutex_lock(&ev->scheduled_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+ DLIST_ADD_END(ev->scheduled_immediates, im);
+
+ ret = pthread_mutex_unlock(&ev->scheduled_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+ /*
+ * We might want to wake up the main thread under the lock. We
+ * had a slightly similar situation in pthreadpool, changed
+ * with 1c4284c7395f23. This is not exactly the same, as the
+ * wakeup is only a last-resort thing in case the main thread
+ * is sleeping. Doing the wakeup under the lock can easily
+ * lead to a contended mutex, which is much more expensive
+ * than a noncontended one. So I'd opt for the lower footprint
+ * initially. Maybe we have to change that later.
+ */
+ tevent_common_wakeup_fd(tctx->wakeup_fd);
+#else
+ /*
+ * tevent_threaded_context_create() returned NULL with ENOSYS...
+ */
+ abort();
+#endif
+}
+
+void tevent_common_threaded_activate_immediate(struct tevent_context *ev)
+{
+#ifdef HAVE_PTHREAD
+ int ret;
+ ret = pthread_mutex_lock(&ev->scheduled_mutex);
+ if (ret != 0) {
+ abort();
+ }
+
+ while (ev->scheduled_immediates != NULL) {
+ struct tevent_immediate *im = ev->scheduled_immediates;
+ DLIST_REMOVE(ev->scheduled_immediates, im);
+ DLIST_ADD_END(ev->immediate_events, im);
+ }
+
+ ret = pthread_mutex_unlock(&ev->scheduled_mutex);
+ if (ret != 0) {
+ abort();
+ }
+#else
+ /*
+ * tevent_threaded_context_create() returned NULL with ENOSYS...
+ */
+ abort();
+#endif
+}
diff --git a/lib/tevent/tevent_timed.c b/lib/tevent/tevent_timed.c
index 920d39f..92f3ed1 100644
--- a/lib/tevent/tevent_timed.c
+++ b/lib/tevent/tevent_timed.c
@@ -154,39 +154,13 @@ static int tevent_common_timed_deny_destructor(struct tevent_timer *te)
return -1;
}
-/*
- add a timed event
- return NULL on failure (memory allocation error)
-*/
-static struct tevent_timer *tevent_common_add_timer_internal(
- struct tevent_context *ev,
- TALLOC_CTX *mem_ctx,
- struct timeval next_event,
- tevent_timer_handler_t handler,
- void *private_data,
- const char *handler_name,
- const char *location,
- bool optimize_zero)
+static void tevent_common_insert_timer(struct tevent_context *ev,
+ struct tevent_timer *te,
+ bool optimize_zero)
{
- struct tevent_timer *te, *prev_te, *cur_te;
-
- te = talloc(mem_ctx?mem_ctx:ev, struct tevent_timer);
- if (te == NULL) return NULL;
-
- te->event_ctx = ev;
- te->next_event = next_event;
- te->handler = handler;
- te->private_data = private_data;
- te->handler_name = handler_name;
- te->location = location;
- te->additional_data = NULL;
-
- if (ev->timer_events == NULL) {
- ev->last_zero_timer = NULL;
- }
+ struct tevent_timer *prev_te = NULL;
/* keep the list ordered */
- prev_te = NULL;
if (optimize_zero && tevent_timeval_is_zero(&te->next_event)) {
/*
* Some callers use zero tevent_timer
@@ -199,6 +173,8 @@ static struct tevent_timer *tevent_common_add_timer_internal(
prev_te = ev->last_zero_timer;
ev->last_zero_timer = te;
} else {
+ struct tevent_timer *cur_te;
+
/*
* we traverse the list from the tail
* because it's much more likely that
@@ -227,6 +203,40 @@ static struct tevent_timer *tevent_common_add_timer_internal(
}
DLIST_ADD_AFTER(ev->timer_events, te, prev_te);
+}
+
+/*
+ add a timed event
+ return NULL on failure (memory allocation error)
+*/
+static struct tevent_timer *tevent_common_add_timer_internal(
+ struct tevent_context *ev,
+ TALLOC_CTX *mem_ctx,
+ struct timeval next_event,
+ tevent_timer_handler_t handler,
+ void *private_data,
+ const char *handler_name,
+ const char *location,
+ bool optimize_zero)
+{
+ struct tevent_timer *te;
+
+ te = talloc(mem_ctx?mem_ctx:ev, struct tevent_timer);
+ if (te == NULL) return NULL;
+
+ te->event_ctx = ev;
+ te->next_event = next_event;
+ te->handler = handler;
+ te->private_data = private_data;
+ te->handler_name = handler_name;
+ te->location = location;
+ te->additional_data = NULL;
+
+ if (ev->timer_events == NULL) {
+ ev->last_zero_timer = NULL;
+ }
+
+ tevent_common_insert_timer(ev, te, optimize_zero);
talloc_set_destructor(te, tevent_common_timed_destructor);
@@ -274,6 +284,24 @@ struct tevent_timer *tevent_common_add_timer_v2(struct tevent_context *ev,
true);
}
+void tevent_update_timer(struct tevent_timer *te, struct timeval next_event)
+{
+ struct tevent_context *ev = te->event_ctx;
+
+ if (ev->last_zero_timer == te) {
+ te->event_ctx->last_zero_timer = DLIST_PREV(te);
+ }
+ DLIST_REMOVE(ev->timer_events, te);
+
+ te->next_event = next_event;
+
+ /*
+ * Not doing the zero_timer optimization. This is for new code
+ * that should know about immediates.
+ */
+ tevent_common_insert_timer(ev, te, false);
+}
+
/*
do a single event loop using the events defined in ev
diff --git a/lib/tevent/wscript b/lib/tevent/wscript
index 501de16..580ca4d 100755
--- a/lib/tevent/wscript
+++ b/lib/tevent/wscript
@@ -1,7 +1,7 @@
#!/usr/bin/env python
APPNAME = 'tevent'
-VERSION = '0.9.27'
+VERSION = '0.9.31'
blddir = 'bin'
@@ -99,9 +99,13 @@ def build(bld):
private_library = True
if not bld.CONFIG_SET('USING_SYSTEM_TEVENT'):
+ tevent_deps = 'replace talloc'
+ if bld.CONFIG_SET('HAVE_PTHREAD'):
+ tevent_deps += ' pthread'
+
bld.SAMBA_LIBRARY('tevent',
SRC,
- deps='replace talloc',
+ deps=tevent_deps,
enabled= not bld.CONFIG_SET('USING_SYSTEM_TEVENT'),
includes='.',
abi_directory='ABI',
diff --git a/modules/paged_results.c b/modules/paged_results.c
index 2d6c62f..de014a3 100644
--- a/modules/paged_results.c
+++ b/modules/paged_results.c
@@ -67,7 +67,7 @@ struct results_store {
};
struct private_data {
- unsigned int next_free_id;
+ uint32_t next_free_id;
struct results_store *store;
};
@@ -96,7 +96,7 @@ static int store_destructor(struct results_store *del)
static struct results_store *new_store(struct private_data *priv)
{
struct results_store *newr;
- unsigned int new_id = priv->next_free_id++;
+ uint32_t new_id = priv->next_free_id++;
/* TODO: we should have a limit on the number of
* outstanding paged searches
diff --git a/modules/rdn_name.c b/modules/rdn_name.c
index f44ea71..e69ad93 100644
--- a/modules/rdn_name.c
+++ b/modules/rdn_name.c
@@ -144,7 +144,7 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
attribute = ldb_msg_find_element(msg, rdn_name);
if (!attribute) {
/* add entry with normalised RDN information if possible */
- if (a->name != NULL) {
+ if (a->name != NULL && strcmp(a->name, "*") != 0) {
ret = ldb_msg_add_value(msg, a->name, &rdn_val, NULL);
} else {
ret = ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL);
@@ -154,7 +154,7 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
}
} else {
/* normalise attribute name if possible */
- if (a->name != NULL) {
+ if (a->name != NULL && strcmp(a->name, "*") != 0) {
attribute->name = a->name;
}
/* normalise attribute value */
@@ -243,6 +243,7 @@ static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
struct rename_context *ac;
struct ldb_request *mod_req;
const char *rdn_name;
+ const struct ldb_schema_attribute *a = NULL;
const struct ldb_val *rdn_val_p;
struct ldb_val rdn_val;
struct ldb_message *msg;
@@ -286,6 +287,15 @@ static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
goto error;
}
+ a = ldb_schema_attribute_by_name(ldb, rdn_name);
+ if (a == NULL) {
+ goto error;
+ }
+
+ if (a->name != NULL && strcmp(a->name, "*") != 0) {
+ rdn_name = a->name;
+ }
+
rdn_val_p = ldb_dn_get_rdn_val(msg->dn);
if (rdn_val_p == NULL) {
goto error;
@@ -367,11 +377,20 @@ static int rdn_name_rename(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, down_req);
}
+static int rdn_recalculate_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+ struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
+
+ talloc_steal(up_req, req);
+ return up_req->callback(up_req, ares);
+}
+
static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_context *ldb;
const struct ldb_val *rdn_val_p;
struct ldb_message_element *e = NULL;
+ struct ldb_control *recalculate_rdn_control = NULL;
ldb = ldb_module_get_ctx(module);
@@ -380,6 +399,138 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
+ recalculate_rdn_control = ldb_request_get_control(req,
+ LDB_CONTROL_RECALCULATE_RDN_OID);
+ if (recalculate_rdn_control != NULL) {
+ struct ldb_message *msg = NULL;
+ const char *rdn_name = NULL;
+ struct ldb_val rdn_val;
+ const struct ldb_schema_attribute *a = NULL;
+ struct ldb_request *mod_req = NULL;
+ int ret;
+ struct ldb_message_element *rdn_del = NULL;
+ struct ldb_message_element *name_del = NULL;
+
+ recalculate_rdn_control->critical = false;
+
+ msg = ldb_msg_copy_shallow(req, req->op.mod.message);
+ if (msg == NULL) {
+ return ldb_module_oom(module);
+ }
+
+ /*
+ * The caller must pass a dummy 'name' attribute
+ * in order to bypass some high level checks.
+ *
+ * We just remove it and check nothing is left.
+ */
+ ldb_msg_remove_attr(msg, "name");
+
+ if (msg->num_elements != 0) {
+ return ldb_module_operr(module);
+ }
+
+ rdn_name = ldb_dn_get_rdn_name(msg->dn);
+ if (rdn_name == NULL) {
+ return ldb_module_oom(module);
+ }
+
+ a = ldb_schema_attribute_by_name(ldb, rdn_name);
+ if (a == NULL) {
+ return ldb_module_operr(module);
+ }
+
+ if (a->name != NULL && strcmp(a->name, "*") != 0) {
+ rdn_name = a->name;
+ }
+
+ rdn_val_p = ldb_dn_get_rdn_val(msg->dn);
+ if (rdn_val_p == NULL) {
+ return ldb_module_oom(module);
+ }
+ rdn_val = ldb_val_dup(msg, rdn_val_p);
+ if (rdn_val.length == 0) {
+ return ldb_module_oom(module);
+ }
+
+ /*
+ * This is a bit tricky:
+ *
+ * We want _DELETE elements (as "rdn_del" and "name_del" without
+ * values) first, followed by _ADD (with the real names)
+ * elements (with values). Then we fix up the "rdn_del" and
+ * "name_del" attributes.
+ */
+
+ ret = ldb_msg_add_empty(msg, "rdn_del", LDB_FLAG_MOD_DELETE, NULL);
+ if (ret != 0) {
+ return ldb_module_oom(module);
+ }
+ ret = ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_ADD, NULL);
+ if (ret != 0) {
+ return ldb_module_oom(module);
+ }
+ ret = ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL);
+ if (ret != 0) {
+ return ldb_module_oom(module);
+ }
+
+ ret = ldb_msg_add_empty(msg, "name_del", LDB_FLAG_MOD_DELETE, NULL);
+ if (ret != 0) {
+ return ldb_module_oom(module);
+ }
+ ret = ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_ADD, NULL);
+ if (ret != 0) {
+ return ldb_module_oom(module);
+ }
+ ret = ldb_msg_add_value(msg, "name", &rdn_val, NULL);
+ if (ret != 0) {
+ return ldb_module_oom(module);
+ }
+
+ rdn_del = ldb_msg_find_element(msg, "rdn_del");
+ if (rdn_del == NULL) {
+ return ldb_module_operr(module);
+ }
+ rdn_del->name = talloc_strdup(msg->elements, rdn_name);
+ if (rdn_del->name == NULL) {
+ return ldb_module_oom(module);
+ }
+ name_del = ldb_msg_find_element(msg, "name_del");
+ if (name_del == NULL) {
+ return ldb_module_operr(module);
+ }
+ name_del->name = talloc_strdup(msg->elements, "name");
+ if (name_del->name == NULL) {
+ return ldb_module_oom(module);
+ }
+
+ ret = ldb_build_mod_req(&mod_req, ldb,
+ req, msg, NULL,
+ req, rdn_recalculate_callback,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(req, NULL, NULL, ret);
+ }
+ talloc_steal(mod_req, msg);
+
+ ret = ldb_request_add_control(mod_req,
+ LDB_CONTROL_RECALCULATE_RDN_OID,
+ false, NULL);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(req, NULL, NULL, ret);
+ }
+ ret = ldb_request_add_control(mod_req,
+ LDB_CONTROL_PERMISSIVE_MODIFY_OID,
+ false, NULL);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(req, NULL, NULL, ret);
+ }
+
+ /* go on with the call chain */
+ return ldb_next_request(module, mod_req);
+ }
+
rdn_val_p = ldb_dn_get_rdn_val(req->op.mod.message->dn);
if (rdn_val_p == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
diff --git a/modules/sort.c b/modules/sort.c
index 1b762f7..cb6f8df 100644
--- a/modules/sort.c
+++ b/modules/sort.c
@@ -56,6 +56,7 @@ struct sort_context {
char **referrals;
unsigned int num_msgs;
unsigned int num_refs;
+ const char *extra_sort_key;
const struct ldb_schema_attribute *a;
int sort_result;
@@ -162,7 +163,9 @@ static int server_sort_results(struct sort_context *ac)
ares->type = LDB_REPLY_ENTRY;
ares->message = talloc_move(ares, &ac->msgs[i]);
-
+ if (ac->extra_sort_key) {
+ ldb_msg_remove_attr(ares->message, ac->extra_sort_key);
+ }
ret = ldb_module_send_entry(ac->req, ares->message, ares->controls);
if (ret != LDB_SUCCESS) {
return ret;
@@ -256,6 +259,9 @@ static int server_sort_search(struct ldb_module *module, struct ldb_request *req
struct sort_context *ac;
struct ldb_context *ldb;
int ret;
+ const char * const *attrs;
+ size_t n_attrs, i;
+ const char *sort_attr;
ldb = ldb_module_get_ctx(module);
@@ -303,6 +309,42 @@ static int server_sort_search(struct ldb_module *module, struct ldb_request *req
}
}
+ control->critical = 0;
+
+ /* We are asked to sort on an attribute, and if that attribute is not
+ already in the search attributes we need to add it (and later
+ remove it on the return journey).
+ */
+ sort_attr = sort_ctrls[0]->attributeName;
+ if (req->op.search.attrs == NULL) {
+ /* This means all non-operational attributes, which means
+ there's nothing to add. */
+ attrs = NULL;
+ } else {
+ n_attrs = 0;
+ while (req->op.search.attrs[n_attrs] != NULL) {
+ if (sort_attr &&
+ strcmp(req->op.search.attrs[n_attrs], sort_attr) == 0) {
+ sort_attr = NULL;
+ }
+ n_attrs++;
+ }
+
+ if (sort_attr == NULL) {
+ attrs = req->op.search.attrs;
+ } else {
+ const char **tmp = talloc_array(ac, const char *, n_attrs + 2);
+
+ for (i = 0; i < n_attrs; i++) {
+ tmp[i] = req->op.search.attrs[i];
+ }
+ ac->extra_sort_key = sort_attr;
+ tmp[n_attrs] = sort_attr;
+ tmp[n_attrs + 1] = NULL;
+ attrs = tmp;
+ }
+ }
+
ac->attributeName = sort_ctrls[0]->attributeName;
ac->orderingRule = sort_ctrls[0]->orderingRule;
ac->reverse = sort_ctrls[0]->reverse;
@@ -311,7 +353,7 @@ static int server_sort_search(struct ldb_module *module, struct ldb_request *req
req->op.search.base,
req->op.search.scope,
req->op.search.tree,
- req->op.search.attrs,
+ attrs,
req->controls,
ac,
server_sort_search_callback,
diff --git a/pyldb.h b/pyldb.h
index f8aea22..4fc89ec 100644
--- a/pyldb.h
+++ b/pyldb.h
@@ -60,11 +60,18 @@ typedef struct {
} PyLdbModuleObject;
#define pyldb_Module_AsModule(pyobj) ((PyLdbModuleObject *)pyobj)->mod
+/*
+ * NOTE: el (and so the return value of
+ * pyldb_MessageElement_AsMessageElement()) may not be a valid talloc
+ * context, it could be part of an array
+ */
+
typedef struct {
PyObject_HEAD
TALLOC_CTX *mem_ctx;
struct ldb_message_element *el;
} PyLdbMessageElementObject;
+
#define pyldb_MessageElement_AsMessageElement(pyobj) ((PyLdbMessageElementObject *)pyobj)->el
typedef struct {
@@ -88,11 +95,12 @@ typedef struct {
struct ldb_control *data;
} PyLdbControlObject;
-#define PyErr_LDB_ERROR_IS_ERR_RAISE(err,ret,ldb) \
+#define PyErr_LDB_ERROR_IS_ERR_RAISE(err,ret,ldb) do { \
if (ret != LDB_SUCCESS) { \
PyErr_SetLdbError(err, ret, ldb); \
return NULL; \
- }
+ } \
+} while(0)
/* Picked out of thin air. To do this properly, we should probably have some part of the
* errors in LDB be allocated to bindings ? */
diff --git a/tests/test-tdb-features.sh b/tests/test-tdb-features.sh
index 59e61ee..a9cd6b3 100644
--- a/tests/test-tdb-features.sh
+++ b/tests/test-tdb-features.sh
@@ -4,6 +4,11 @@ echo "Running tdb feature tests"
mv $LDB_URL $LDB_URL.2
+cat <<EOF | $VALGRIND ldbadd || exit 1
+dn: @MODULES
+@LIST: rdn_name
+EOF
+
checkcount() {
count=$1
expression="$2"
@@ -25,6 +30,7 @@ EOF
checkcount 1 '(test=foo)'
checkcount 0 '(test=FOO)'
checkcount 0 '(test=FO*)'
+checkcount 1 '(cn=t1)'
echo "Making case insensitive"
cat <<EOF | $VALGRIND ldbmodify || exit 1
@@ -79,6 +85,13 @@ EOF
checkcount 1 '(j=0x100)'
checkcount 1 '(j=256)'
+cat <<EOF | $VALGRIND ldbadd || exit 1
+dn: num=1
+EOF
+
+echo "Testing search for attribute after change to use wildcard"
+checkcount 1 '(num=1)'
+
echo "Testing class search"
checkcount 0 '(objectClass=otherclass)'
checkcount 1 '(objectClass=testclass)'
diff --git a/tools/ldbdump.c b/tools/ldbdump.c
index 3197d19..33f853d 100644
--- a/tools/ldbdump.c
+++ b/tools/ldbdump.c
@@ -110,6 +110,9 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA _dbuf, void *sta
}
static void log_stderr(struct tdb_context *tdb, enum tdb_debug_level level,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+
+static void log_stderr(struct tdb_context *tdb, enum tdb_debug_level level,
const char *fmt, ...)
{
va_list ap;
diff --git a/tools/ldbutil.h b/tools/ldbutil.h
index f8d3f3a..6723863 100644
--- a/tools/ldbutil.h
+++ b/tools/ldbutil.h
@@ -43,4 +43,4 @@ int ldb_search_ctrl(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
struct ldb_result **result, struct ldb_dn *base,
enum ldb_scope scope, const char * const *attrs,
struct ldb_control **controls,
- const char *exp_fmt, ...);
+ const char *exp_fmt, ...) PRINTF_ATTRIBUTE(8,9);
diff --git a/wscript b/wscript
index 2398ff7..7f05db3 100755
--- a/wscript
+++ b/wscript
@@ -1,7 +1,7 @@
#!/usr/bin/env python
APPNAME = 'ldb'
-VERSION = '1.1.26'
+VERSION = '1.1.29'
blddir = 'bin'